diff --git a/lib/adminlib.php b/lib/adminlib.php index 123235efde0..68ec79f7f48 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -9524,116 +9524,25 @@ class admin_setting_managewebservicetokens extends admin_setting { * @return string */ public function output_html($data, $query='') { - global $CFG, $OUTPUT, $DB, $USER; + global $CFG, $OUTPUT; - // display strings - $stroperation = get_string('operation', 'webservice'); - $strtoken = get_string('token', 'webservice'); - $strservice = get_string('service', 'webservice'); - $struser = get_string('user'); - $strcreator = get_string('tokencreator', 'webservice'); - $strcontext = get_string('context', 'webservice'); - $strvaliduntil = get_string('validuntil', 'webservice'); - $striprestriction = get_string('iprestriction', 'webservice'); + require_once($CFG->dirroot . '/webservice/classes/token_table.php'); + $baseurl = new moodle_url('/' . $CFG->admin . '/settings.php?section=webservicetokens'); $return = $OUTPUT->box_start('generalbox webservicestokenui'); - $showalltokens = has_capability('moodle/webservice:managealltokens', context_system::instance()); - - $table = new html_table(); - if ($showalltokens) { - $table->head = array($strtoken, $struser, $strservice, $striprestriction, $strvaliduntil, $strcreator, $stroperation); - } else { - $table->head = array($strtoken, $struser, $strservice, $striprestriction, $strvaliduntil, $stroperation); - } - $table->colclasses = array('leftalign', 'leftalign', 'leftalign', 'centeralign', 'centeralign', 'leftalign', 'centeralign'); - $table->id = 'webservicetokens'; - $table->attributes['class'] = 'admintable generaltable'; + $table = new \webservice\token_table('webservicetokens'); + $table->define_baseurl($baseurl); + $table->attributes['class'] = 'admintable generaltable'; // Any need changing? $table->data = array(); + ob_start(); + $table->out(10, false); + $tablehtml = ob_get_contents(); + ob_end_clean(); + $return .= $tablehtml; $tokenpageurl = "$CFG->wwwroot/$CFG->admin/webservice/tokens.php?sesskey=" . sesskey(); - //TODO: in order to let the administrator delete obsolete token, split this request in multiple request or use LEFT JOIN - - $params = []; - //here retrieve token list (including linked users firstname/lastname and linked services name) - if ($showalltokens) { - // Show all tokens. - $sql = "SELECT t.id, t.token, u.id AS userid, u.firstname, u.lastname, s.name, t.iprestriction, t.validuntil, s.id AS serviceid, t.creatorid, c.username creator - FROM {external_tokens} t, {user} u, {external_services} s, {user} c - WHERE t.tokentype = ? AND s.id = t.externalserviceid AND t.userid = u.id AND c.id = t.creatorid"; - $params = [EXTERNAL_TOKEN_PERMANENT]; - } else { - // Only show tokens created by the current user. - $sql = "SELECT t.id, t.token, u.id AS userid, u.firstname, u.lastname, s.name, t.iprestriction, t.validuntil, s.id AS serviceid, t.creatorid, c.username creator - FROM {external_tokens} t, {user} u, {external_services} s, {user} c - WHERE t.creatorid=? AND t.tokentype = ? AND s.id = t.externalserviceid AND t.userid = u.id AND c.id = t.creatorid"; - $params = [$USER->id, EXTERNAL_TOKEN_PERMANENT]; - } - $tokens = $DB->get_records_sql($sql, $params); - if (!empty($tokens)) { - foreach ($tokens as $token) { - //TODO: retrieve context - - $delete = "id."\">"; - $delete .= get_string('delete').""; - - $validuntil = ''; - if (!empty($token->validuntil)) { - $validuntil = userdate($token->validuntil, get_string('strftimedatetime', 'langconfig')); - } - - $iprestriction = ''; - if (!empty($token->iprestriction)) { - $iprestriction = $token->iprestriction; - } - - $userprofilurl = new moodle_url('/user/profile.php?id='.$token->userid); - $useratag = html_writer::start_tag('a', array('href' => $userprofilurl)); - $useratag .= $token->firstname." ".$token->lastname; - $useratag .= html_writer::end_tag('a'); - - //check user missing capabilities - require_once($CFG->dirroot . '/webservice/lib.php'); - $webservicemanager = new webservice(); - $usermissingcaps = $webservicemanager->get_missing_capabilities_by_users( - array(array('id' => $token->userid)), $token->serviceid); - - if (!is_siteadmin($token->userid) and - array_key_exists($token->userid, $usermissingcaps)) { - $missingcapabilities = implode(', ', - $usermissingcaps[$token->userid]); - if (!empty($missingcapabilities)) { - $useratag .= html_writer::tag('div', - get_string('usermissingcaps', 'webservice', - $missingcapabilities) - . ' ' . $OUTPUT->help_icon('missingcaps', 'webservice'), - array('class' => 'missingcaps')); - } - } - - $creatorprofileurl = new moodle_url('/user/profile.php?id='.$token->creatorid); - $creatoratag = html_writer::start_tag('a', array('href' => $creatorprofileurl)); - $creatoratag .= $token->creator; - $creatoratag .= html_writer::end_tag('a'); - - if ($token->creatorid != $USER->id) { // TODO: is creatorid NOT NULL? What if it's NULL? - $token->token = ''; - // TODO: Should I also remove permissions? - } - - if ($showalltokens) { - $table->data[] = array($token->token, $useratag, $token->name, $iprestriction, $validuntil, $creatoratag, $delete); - } else { - $table->data[] = array($token->token, $useratag, $token->name, $iprestriction, $validuntil, $delete); - } - } - - $return .= html_writer::table($table); - } else { - $return .= get_string('notoken', 'webservice'); - } - $return .= $OUTPUT->box_end(); // add a token to the table $return .= ""; diff --git a/webservice/classes/token_table.php b/webservice/classes/token_table.php new file mode 100644 index 00000000000..fba6aa2787e --- /dev/null +++ b/webservice/classes/token_table.php @@ -0,0 +1,260 @@ +. + +/** + * Contains the class used for the displaying the tokens table. + * + * @package core_webservice + * @copyright 2017 John Okely + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace webservice; + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->libdir . '/tablelib.php'); +require_once($CFG->dirroot . '/webservice/lib.php'); +require_once($CFG->dirroot . '/user/lib.php'); + +/** + * Class for the displaying the participants table. + * + * @package core_webservice + * @copyright 2017 John Okely + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class token_table extends \table_sql { + + /** + * @var bool $showalltokens Whether or not the user is able to see all tokens. + */ + protected $showalltokens; + + /** + * Sets up the table. + * @param int $id The id of the table + */ + public function __construct($id) { + parent::__construct($id); + + // Get the context. + $context = \context_system::instance(); + + // Can we see tokens created by all users? + $this->showalltokens = has_capability('moodle/webservice:managealltokens', $context); + + // Define the headers and columns. + $headers = []; + $columns = []; + + $headers[] = get_string('token', 'webservice'); + $columns[] = 'token'; + $headers[] = get_string('user'); + $columns[] = 'fullname'; + $headers[] = get_string('service', 'webservice'); + $columns[] = 'name'; + $headers[] = get_string('iprestriction', 'webservice'); + $columns[] = 'iprestriction'; + $headers[] = get_string('validuntil', 'webservice'); + $columns[] = 'validuntil'; + if ($this->showalltokens) { + // Only need to show creator if you can see tokens created by other people. + $headers[] = get_string('tokencreator', 'webservice'); + $columns[] = 'creatorlastname'; // So we can have semi-useful sorting. Table SQL doesn't two fullname collumns. + } + $headers[] = get_string('operation', 'webservice'); + $columns[] = 'operation'; + + $this->define_columns($columns); + $this->define_headers($headers); + + $this->no_sorting('operation'); + $this->no_sorting('token'); + $this->no_sorting('iprestriction'); + + $this->set_attribute('id', $id); + } + + /** + * Generate the operation column. + * + * @param \stdClass $data Data for the current row + * @return string Content for the column + */ + public function col_operation($data) { + $tokenpageurl = new \moodle_url( + "/admin/webservice/tokens.php", + [ + "sesskey" => sesskey(), + "action" => "delete", + "tokenid" => $data->id + ] + ); + return \html_writer::link($tokenpageurl, get_string("delete")); + } + + /** + * Generate the validuntil column. + * + * @param \stdClass $data Data for the current row + * @return string Content for the column + */ + public function col_validuntil($data) { + if (empty($data->validuntil)) { + return ''; + } else { + return userdate($data->validuntil, get_string('strftimedatetime', 'langconfig')); + } + } + + /** + * Generate the fullname column. Also includes capabilities the user is missing for the webservice (if any) + * + * @param \stdClass $data Data for the current row + * @return string Content for the column + */ + public function col_fullname($data) { + global $OUTPUT; + + $userprofilurl = new \moodle_url('/user/profile.php', ['id' => $data->userid]); + $content = \html_writer::link($userprofilurl, fullname($data)); + + // Make up list of capabilities that the user is missing for the given webservice. + $webservicemanager = new \webservice(); + $usermissingcaps = $webservicemanager->get_missing_capabilities_by_users([['id' => $data->userid]], $data->serviceid); + + if (!is_siteadmin($data->userid) && array_key_exists($data->userid, $usermissingcaps)) { + $missingcapabilities = implode(', ', $usermissingcaps[$data->userid]); + if (!empty($missingcapabilities)) { + $capabilitiesstring = get_string('usermissingcaps', 'webservice', $missingcapabilities) . ' ' . + $OUTPUT->help_icon('missingcaps', 'webservice'); + $content .= \html_writer::div($capabilitiesstring, 'missingcaps'); + } + } + + return $content; + } + + /** + * Generate the token column. + * + * @param \stdClass $data Data for the current row + * @return string Content for the column + */ + public function col_token($data) { + global $USER; + // Hide the token if it wasn't created by the current user. + if ($data->creatorid != $USER->id) { + return ''; + } + + return $data->token; + } + + /** + * Generate the creator column. + * + * @param \stdClass $data + * @return string + */ + public function col_creatorlastname($data) { + // We have loaded all the name fields for the creator, with the 'creator' prefix. + // So just remove the prefix and make up a user object. + $user = []; + foreach ($data as $key => $value) { + if (strpos($key, 'creator') !== false) { + $newkey = str_replace('creator', '', $key); + $user[$newkey] = $value; + } + } + + $creatorprofileurl = new \moodle_url('/user/profile.php', ['id' => $data->creatorid]); + return \html_writer::link($creatorprofileurl, fullname((object)$user)); + } + + /** + * This function is used for the extra user fields. + * + * These are being dynamically added to the table so there are no functions 'col_' as + * the list has the potential to increase in the future and we don't want to have to remember to add + * a new method to this class. We also don't want to pollute this class with unnecessary methods. + * + * @param string $colname The column name + * @param \stdClass $data + * @return string + */ + public function other_cols($colname, $data) { + return s($data->{$colname}); + } + + /** + * Query the database for results to display in the table. + * + * Note: Initial bars are not implemented for this table because it includes user details twice and the initial bars do not work + * when the user table is included more than once. + * + * @param int $pagesize size of page for paginated displayed table. + * @param bool $useinitialsbar Not implemented. Please pass false. + */ + public function query_db($pagesize, $useinitialsbar = false) { + global $DB, $USER; + + if ($useinitialsbar) { + debugging('Initial bar not implemented yet. Call out($pagesize, false)'); + } + + $usernamefields = get_all_user_name_fields(true, 'u'); + $creatorfields = get_all_user_name_fields(true, 'c', null, 'creator'); + + $params = ["tokenmode" => EXTERNAL_TOKEN_PERMANENT]; + + // TODO: in order to let the administrator delete obsolete token, split the request in multiple request or use LEFT JOIN. + + if ($this->showalltokens) { + // Show all tokens. + $sql = "SELECT t.id, t.token, u.id AS userid, $usernamefields, s.name, t.iprestriction, t.validuntil, s.id AS serviceid, + t.creatorid, $creatorfields + FROM {external_tokens} t, {user} u, {external_services} s, {user} c + WHERE t.tokentype = :tokenmode AND s.id = t.externalserviceid AND t.userid = u.id AND c.id = t.creatorid"; + $countsql = "SELECT COUNT(t.id) + FROM {external_tokens} t, {user} u, {external_services} s, {user} c + WHERE t.tokentype = :tokenmode AND s.id = t.externalserviceid AND t.userid = u.id AND c.id = t.creatorid"; + } else { + // Only show tokens created by the current user. + $sql = "SELECT t.id, t.token, u.id AS userid, $usernamefields, s.name, t.iprestriction, t.validuntil, s.id AS serviceid, + t.creatorid, $creatorfields + FROM {external_tokens} t, {user} u, {external_services} s, {user} c + WHERE t.creatorid=:userid AND t.tokentype = :tokenmode AND s.id = t.externalserviceid AND t.userid = u.id AND + c.id = t.creatorid"; + $countsql = "SELECT COUNT(t.id) + FROM {external_tokens} t, {user} u, {external_services} s, {user} c + WHERE t.creatorid=:userid AND t.tokentype = :tokenmode AND s.id = t.externalserviceid AND + t.userid = u.id AND c.id = t.creatorid"; + $params["userid"] = $USER->id; + } + + $sort = $this->get_sql_sort(); + if ($sort) { + $sql = $sql . ' ORDER BY ' . $sort; + } + + $total = $DB->count_records_sql($countsql, $params); + $this->pagesize($pagesize, $total); + + $this->rawdata = $DB->get_recordset_sql($sql, $params, $this->get_page_start(), $this->get_page_size()); + } +}