Commit ce1a97ac authored by Aaron Wells's avatar Aaron Wells
Browse files

Bug 1600099: Cleanup of the webservice admin page

This patch does a few things:

1. Renames "webservice_enabled" config to "webservice_provider_enabled",
to indicate that this config only controls Mahara's actions as
a webservice provider, *not* a webservice client.

2. Renames all the "webservice_<protocol>_enabled" configs to
"webservice_provider_<protocol>_enabled" to indicate that they only
control whether Mahara will provide webservices via that protocol,
and not whether Mahara will use that protocol as a client.

3. Renames "webservice_connections_enabled" config to
"webservice_requester_enabled", to clarify that this config
controls whether Mahara is allowed to request webservices
from external sources.

4. Updates language strings to make these changes clearer.

5. Rearranges and renames the form methods in
webservice/admin/index.php to make the flow of control more
obvious. Now the main form method is first, followed in order
by the methods that generate its subforms and each of their
submit handlers.

behatnotneeded: Covered by existing tests

Change-Id: I58dadb352d1f1542ca67a104ebfd702b4ca90fc9
parent 8e4a1f64
......@@ -462,6 +462,27 @@ function xmldb_auth_webservice_upgrade($oldversion=0) {
}
}
if ($oldversion < 2016071400) {
log_debug('Updating DB names of webservice config fields');
$configstochange = array(
'webservice_enabled' => 'webservice_provider_enabled',
'webservice_soap_enabled' => 'webservice_provider_soap_enabled',
'webservice_xmlrpc_enabled' => 'webservice_provider_xmlrpc_enabled',
'webservice_rest_enabled' => 'webservice_provider_rest_enabled',
'webservice_oauth_enabled' => 'webservice_provider_oauth_enabled',
'webservice_connections_enabled' => 'webservice_requester_enabled'
);
foreach ($configstochange as $old => $new) {
set_config(
$new,
get_config($old)
);
delete_records('config', 'field', $old);
}
}
// sweep for webservice updates everytime
$status = external_reload_webservices();
......
......@@ -84,15 +84,15 @@ $string['consumer'] = 'Consumer key';
$string['secret'] = 'Secret';
// core webservices strings start here
$string['control_webservices1'] = 'Use web services: ';
$string['control_webservices'] = 'Switch web services on or off: ';
$string['control_webservices_connections'] = 'Switch web service connections on or off: ';
$string['masterswitch'] = 'Web services master switch';
$string['connectionsmasterswitch'] = 'Web service client connections master switch';
$string['webservice_requester_enabled_label'] = 'Web service requester master switch';
$string['webservice_requester_enabled_label2'] = 'Allow outgoing web service requests:';
$string['webservice_provider_enabled_label'] = 'Web service provider master switch';
$string['webservice_provider_enabled_label2'] = 'Accept incoming web service requests:';
$string['formatdate'] = '';
$string['protocolswitches'] = 'Switch protocols on or off';
$string['webservice_master_switches'] = 'Enable web service functionality';
$string['connectionsswitch'] = 'Switch managed client connections on or off';
$string['manage_protocols'] = 'Enable or disable protocols that are to be supported:';
$string['manage_protocols1'] = 'Enable or disable protocols supported as a web services provider:';
$string['protocol'] = 'Protocol';
$string['rest'] = 'REST';
$string['soap'] = 'SOAP';
......
......@@ -188,7 +188,7 @@ class PluginAuthWebservice extends PluginAuth {
// activate webservices
foreach (array('soap', 'xmlrpc', 'rest', 'oauth') as $proto) {
set_config('webservice_' . $proto.'_enabled', 1);
set_config('webservice_provider_' . $proto.'_enabled', 1);
}
}
}
......
......@@ -12,7 +12,7 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2014112800;
$config->release = '1.0.1';
$config->version = 2016071400;
$config->release = '1.1.0';
$config->requires_config = 0;
$config->requires_parent = 0;
......@@ -2058,7 +2058,7 @@ abstract class Plugin implements IPlugin {
global $USER;
// is the web service connection switch enabled?
if (!get_config('webservice_connections_enabled')) {
if (!get_config('webservice_requester_enabled')) {
log_debug('get_webservice_connections: disabled');
return array();
}
......
......@@ -16,7 +16,7 @@ $config = new stdClass();
// See https://wiki.mahara.org/wiki/Developer_Area/Version_Numbering_Policy
// For upgrades on stable branches, increment the version by one. On master, use the date.
$config->version = 2016082400;
$config->version = 2016082900;
$config->series = '16.10';
$config->release = '16.10dev';
$config->minupgradefrom = 2012080604;
......
......@@ -22,7 +22,7 @@ define('TITLE', get_string('webservices_title', 'auth.webservice'));
safe_require('auth', 'webservice');
$heading = get_string('webservices_title', 'auth.webservice');
$form = get_config_options_extended();
$form = webservice_admin_main_form();
$serviceenabled = get_string('webservicesenabled', 'auth.webservice');
$servicenotenabled = get_string('webservicesnotenabled', 'auth.webservice');
......@@ -30,10 +30,15 @@ $inlinejs = <<<JS
jQuery(function ($) {
var webservicesenabled = '$serviceenabled';
var webservicesnotenabled = '$servicenotenabled';
if (!$('#needprotocols').length) {
$('#webservice_provider_enabled_form_enabled_container').append('<span id="needprotocols" class="form-message-inline"></span>');
}
function save_protos_switch(name) {
// Check if we have master switch and at least one protocol active
var master = $('#activate_webservices').find('input:checkbox');
var target = $('#activate_webservices').siblings('.form-group').find('input:checkbox');
var master = $('#webservice_provider_enabled_form').find('input:checkbox');
var target = $('.webservice-provider-protocol-form').find('input:checkbox');
if ($(master).filter(':checked').length) {
// master switch is on
......@@ -50,18 +55,34 @@ $inlinejs = <<<JS
// Save new state
if (!$('#ajax_' + name).length) {
$('#activate_webservice_protos_' + name).append('<input id="ajax_' + name + '" type="hidden" name="ajax" value="1">');
$('#webservice_provider_protocols_' + name).append('<input id="ajax_' + name + '" type="hidden" name="ajax" value="1">');
}
$.post('index.php', $('#activate_webservice_protos_' + name).serialize());
$.post('index.php', $('#webservice_provider_protocols_' + name).serialize());
}
if (!$('#needprotocols').length) {
$('#activate_webservices_enabled_container').append('<span id="needprotocols" class="form-message-inline"></span>');
}
// saving the form when switching the protocols
$('#webservice_provider_protocols_soap_enabled').change(function() {
save_protos_switch('soap');
});
$('#webservice_provider_protocols_xmlrpc_enabled').change(function() {
save_protos_switch('xmlrpc');
});
$('#webservice_provider_protocols_rest_enabled').change(function() {
save_protos_switch('rest');
});
$('#webservice_provider_protocols_oauth_enabled').change(function() {
save_protos_switch('oauth');
});
$('#webservice_requester_enabled_form_enabled').on('change', function() {
// save master connection switch form
$('#webservice_requester_enabled_form').append('<input type="hidden" name="ajax" value="1">');
$.post('index.php', $('#webservice_requester_enabled_form').serialize());
});
$('#activate_webservices_enabled').on('change', function() {
var target = $(this).closest('form').siblings('.form-group').find('input:checkbox');
if ($(this).is(':checked')) {
function update_webservice_provider_status() {
var target = $('.webservice-provider-protocol-form').find('input:checkbox');
if ($('#webservice_provider_enabled_form_enabled').is(':checked')) {
// alert user to switch protocols on if none are active
if (target.filter(':checked').length === 0) {
$('#needprotocols').removeClass('text-success').addClass('text-danger').text(webservicesnotenabled);
......@@ -73,30 +94,17 @@ $inlinejs = <<<JS
else {
// turn all protocols off
target.prop('checked', false);
$('#activate_webservices').append('<input type="hidden" name="ajax" value="1">');
$('#activate_webservices_pseudofieldset .form-message-inline').text('');
$('#webservice_provider_enabled_form').append('<input type="hidden" name="ajax" value="1">');
$('#webservice_provider_enabled_form_pseudofieldset .form-message-inline').text('');
}
}
$('#webservice_provider_enabled_form_enabled').on('change', function(){
update_webservice_provider_status();
// save master switch form
$.post('index.php', $('#activate_webservices').serialize());
});
// saving the form when switching the protocols
$('#activate_webservice_protos_soap_enabled').change(function() {
save_protos_switch('soap');
});
$('#activate_webservice_protos_xmlrpc_enabled').change(function() {
save_protos_switch('xmlrpc');
});
$('#activate_webservice_protos_rest_enabled').change(function() {
save_protos_switch('rest');
});
$('#activate_webservice_protos_oauth_enabled').change(function() {
save_protos_switch('oauth');
$.post('index.php', $('#webservice_provider_enabled_form').serialize());
});
$('#activate_connections_enabled').on('change', function() {
// save master connection switch form
$.post('index.php', $('#activate_connections').serialize());
});
update_webservice_provider_status();
});
JS;
......@@ -110,208 +118,227 @@ $smarty->assign('INLINEJAVASCRIPT', $inlinejs);
$smarty->assign('pagedescription', get_string('webservicesconfigdesc', 'auth.webservice'));
$smarty->display('auth:webservice:configform.tpl');
/* pieforms callback for activate_webservices for
/**
* Custom webservices config page
* - activate/deactivate webservices comletely
* - activate/deactivat protocols - SOAP/XML-RPC/REST
* - manage service clusters
* - manage users and access tokens
*
* @return pieforms $element array
*/
function activate_webservices_submit(Pieform $form, $values) {
function webservice_admin_main_form() {
$enabled = $values['enabled'] ? 0 : 1;
set_config('webservice_enabled', $enabled);
$protosform = array(
'name' => 'webservice_provider_protocols_form',
'elements' => webservice_provider_protocols_form(),
);
$protos = pieform_instance($protosform);
// reload/upgrade the web services configuration
if ($enabled) {
// ensure that we have a webservice auth_instance
$authinstance = get_record('auth_instance', 'institution', 'mahara', 'authname', 'webservice');
if (empty($authinstance)) {
$authinstance = (object)array(
'instancename' => 'webservice',
'priority' => 2,
'institution' => 'mahara',
'authname' => 'webservice',
);
insert_record('auth_instance', $authinstance);
}
external_reload_webservices();
}
if (!empty($_POST['ajax'])) {
$protos = array('soap','xmlrpc','rest','oauth');
foreach ($protos as $proto) {
set_config('webservice_'.$proto.'_enabled', 0);
}
exit;
}
redirect('/webservice/admin/index.php');
}
// certificate values from MNet
$openssl = OpenSslRepo::singleton();
function activate_webservice_proto_submit(Pieform $form, $values) {
$enabled = $values['enabled'] ? 0 : 1;
$proto = $values['protocol'];
set_config('webservice_'.$proto.'_enabled', $enabled);
if (!empty($_POST['ajax'])) {
exit;
}
redirect('/webservice/admin/index.php');
}
$elements = array(
// fieldset of master switch
'webservicesmaster' => array(
'name' => 'webservice_master_switches',
'type' => 'fieldset',
'legend' => get_string('webservice_master_switches', 'auth.webservice'),
'elements' => array(
'webservice_requester_enabled_label' => array(
'type' => 'html',
'value' => '<h4>' . get_string('webservice_requester_enabled_label', 'auth.webservice') . '</h4>',
),
'webservice_requester_enabled_fieldset' => webservice_requester_enabled_form(),
'webservice_provider_enabled_label' => array(
'type' => 'html',
'value' => '<h4>' . get_string('webservice_provider_enabled_label', 'auth.webservice') . '</h4>',
),
'webservice_provider_enabled_fieldset' => webservice_provider_enabled_form(),
'protos_help' => array(
'type' => 'html',
'value' => '<div><p>' . get_string('manage_protocols1', 'auth.webservice') . '</p></div>',
),
'webservice_provider_protocols_form' => array(
'type' => 'html',
'value' => $protos->build(false),
)
),
'collapsible' => true,
'collapsed' => true,
),
// System Certificates
'certificates' => array(
'name' => 'activate_webservices_networking',
'type' => 'fieldset',
'legend' => get_string('certificates', 'auth.webservice'),
'elements' => array(
'protos_help' => array(
'type' => 'html',
'value' => '<div><p>' . get_string('manage_certificates', 'auth.webservice', get_config('wwwroot') . 'admin/site/networking.php') . '</p></div>',
),
function webservices_function_groups_submit(Pieform $form, $values) {
global $SESSION;
'pubkey' => array(
'type' => 'html',
'value' => '<h3 class="title">' . get_string('publickey','admin') . '</h3>'
. '<div class="detail">' . get_string('publickeydescription2', 'admin', 365) . '</div>'
. '<pre style="font-size: 0.7em; white-space: pre;">' . $openssl->certificate . '</pre>'
),
'sha1fingerprint' => array(
'type' => 'html',
'value' => '<div><p>' . get_string('sha1fingerprint', 'auth.webservice', $openssl->sha1_fingerprint) . '</p></div>',
),
'md5fingerprint' => array(
'type' => 'html',
'value' => '<div><p>' . get_string('md5fingerprint', 'auth.webservice', $openssl->md5_fingerprint) . '</p></div>',
),
'expires' => array(
'type' => 'html',
'value' => '<div><p>' . get_string('publickeyexpireson','auth.webservice', format_date($openssl->expires)) . '</p></div>'
),
),
'collapsible' => true,
'collapsed' => true,
),
// fieldset for managing service function groups
'servicefunctiongroups' => array(
'name' => 'webservices_function_groups',
'type' => 'fieldset',
'legend' => get_string('servicefunctiongroups', 'auth.webservice'),
'elements' => array(
'sfgdescription' => array(
'value' => '<div><p>' . get_string('sfgdescription', 'auth.webservice') . '</p></div>'
),
'webservicesservicecontainer' => array(
'type' => 'html',
'value' => webservice_function_groups_form(),
)
),
'collapsible' => true,
'collapsed' => true,
),
if ($values['action'] == 'add') {
$service = preg_replace('/[^a-zA-Z0-9_ ]+/', '', $values['service']);
$service = trim($service);
if (empty($service) || record_exists('external_services', 'name', $service)) {
$SESSION->add_error_msg(get_string('invalidinput', 'auth.webservice'));
}
else {
$service = array('name' => $service, 'restrictedusers' => 0, 'enabled' => 0, 'tokenusers' => 0, 'component' => 'webservice', 'ctime' => db_format_timestamp(time()));
insert_record('external_services', $service);
$SESSION->add_ok_msg(get_string('configsaved', 'auth.webservice'));
}
}
else {
$service = get_record('external_services', 'id', $values['service']);
if (!empty($service)) {
if ($values['action'] == 'edit') {
redirect('/webservice/admin/serviceconfig.php?service=' . $values['service']);
}
else if ($values['action'] == 'delete') {
// remove everything associated with a service
$params = array($values['service']);
delete_records_select('external_tokens', "externalserviceid = ?", $params);
delete_records_select('external_services_users', "externalserviceid = ?", $params);
delete_records_select('external_services_functions', "externalserviceid = ?", $params);
delete_records('external_services', 'id', $values['service']);
$SESSION->add_ok_msg(get_string('configsaved', 'auth.webservice'));
}
}
}
// default back to where we came from
redirect('/webservice/admin/index.php?open=webservices_function_groups');
}
// fieldset for managing service tokens
'servicetokens' => array(
'name' => 'webservices_token',
'type' => 'fieldset',
'legend' => get_string('servicetokens', 'auth.webservice'),
'elements' => array(
'stdescription' => array(
'value' => '<div><p>' . get_string('stdescription', 'auth.webservice') . '</p></div>'
),
'webservicestokenscontainer' => array(
'type' => 'html',
'value' => webservice_tokens_form()
)
),
'collapsible' => true,
'collapsed' => false,
),
// fieldset for managing service tokens
'serviceusers' => array(
'name' => 'webservices_user',
'type' => 'fieldset',
'legend' => get_string('manageserviceusers', 'auth.webservice'),
'elements' => array(
'sudescription' => array(
'value' => '<div><p>' . get_string('sudescription', 'auth.webservice') . '</p></div>'
),
'webservicesuserscontainer' => array(
'type' => 'html',
'value' => webservice_users_form(),
)
),
'collapsible' => true,
'collapsed' => false,
),
);
function webservices_token_submit(Pieform $form, $values) {
global $SESSION, $USER;
$form = array(
'renderer' => 'div',
'type' => 'div',
'elements' => $elements,
);
if ($values['action'] == 'generate') {
if (!empty($values['userid'][0])) {
$dbuser = get_record('usr', 'id', $values['userid'][0]);
if (!empty($dbuser)) {
$services = get_records_array('external_services', 'restrictedusers', 0);
if (empty($services)) {
$SESSION->add_error_msg(get_string('noservices', 'auth.webservice'));
}
else {
// just pass the first one for the moment
$service = array_shift($services);
$token = webservice_generate_token(EXTERNAL_TOKEN_PERMANENT, $service, $dbuser->id);
$dbtoken = get_record('external_tokens', 'token', $token);
redirect('/webservice/admin/tokenconfig.php?token=' . $dbtoken->id);
}
}
else {
$SESSION->add_error_msg(get_string('invaliduserselected', 'auth.webservice'));
}
}
else {
$SESSION->add_error_msg(get_string('nouser', 'auth.webservice'));
}
return $form;
}
}
else {
$token = get_record('external_tokens', 'id', $values['token']);
if (!empty($token)) {
if ($values['action'] == 'edit') {
redirect('/webservice/admin/tokenconfig.php?token=' . $values['token']);
}
else if ($values['action'] == 'delete') {
// remove everything associated with a service
$params = array($values['token']);
delete_records_select('external_tokens', "id = ?", $params);
$SESSION->add_ok_msg(get_string('configsaved', 'auth.webservice'));
}
}
}
// default back to where we came from
redirect('/webservice/admin/index.php?open=webservices_token');
/**
* Form layout for the master switch to control whether this site can
* use webservices provided by an external server.
*
* @return pieforms $element array
*/
function webservice_requester_enabled_form() {
// enable/disable webservices completely
$enabled = (get_config('webservice_requester_enabled') || 0);
$element = array(
'type' => 'html',
'value' =>
pieform(
array(
'name' => 'webservice_requester_enabled_form',
'elementclasses' => false,
'class' => 'form-switch form-group',
'successcallback' => 'webservice_requester_enabled_submit',
'renderer' => 'div',
'jsform' => false,
'checkdirtychange' => false,
'elements' => array(
'plugintype' => array('type' => 'hidden', 'value' => 'auth'),
'type' => array('type' => 'hidden', 'value' => 'webservice'),
'pluginname' => array('type' => 'hidden', 'value' => 'webservice'),
'enabled' => array('type' => 'switchbox',
'class' => 'switchbox last',
'value' => $enabled,
'labelhtml' => '<span class="pseudolabel">'. get_string('webservice_requester_enabled_label2', 'auth.webservice') .'</span>',
),
),
)
),
);
return $element;
}
function webservices_user_submit(Pieform $form, $values) {
global $SESSION, $USER;
if ($values['action'] == 'add') {
if (!empty($values['userid'][0])) {
$dbuser = get_record('usr', 'id', $values['userid'][0]);
if ($auth_instance = webservice_validate_user($dbuser)) {
// make sure that this account is not already in use
$existing = get_record('external_services_users', 'userid', $dbuser->id);
if (empty($existing)) {
$services = get_records_array('external_services', 'restrictedusers', 1);
if (empty($services)) {
$SESSION->add_error_msg(get_string('noservices', 'auth.webservice'));
}
else {
// just pass the first one for the moment
$service = array_shift($services);
$dbserviceuser = (object) array('externalserviceid' => $service->id,
'userid' => $dbuser->id,
'institution' => $auth_instance->institution,
'ctime' => db_format_timestamp(time()),
'publickeyexpires' => time(),
'wssigenc' => 0,
'publickey' => '');
$dbserviceuser->id = insert_record('external_services_users', $dbserviceuser, 'id', true);
redirect('/webservice/admin/userconfig.php?suid=' . $dbserviceuser->id);
}
}
else {
$SESSION->add_error_msg(get_string('duplicateuser', 'auth.webservice'));
}
}
else {
$SESSION->add_error_msg(get_string('invaliduserselected', 'auth.webservice'));
}
}
else {
$SESSION->add_error_msg(get_string('nouser', 'auth.webservice'));
}
}
else {
$dbserviceuser = get_record('external_services_users', 'id', $values['suid']);
if (!empty($dbserviceuser)) {
if ($values['action'] == 'edit') {
redirect('/webservice/admin/userconfig.php?suid=' . $values['suid']);
}
else if ($values['action'] == 'delete') {
// remove everything associated with a service
$params = array($values['suid']);
delete_records_select('external_services_users', "id = ?", $params);
$SESSION->add_ok_msg(get_string('configsaved', 'auth.webservice'));
}
}
}
/**
* Pieforms submit callback for Webservices Requester form
*/
function webservice_requester_enabled_submit(Pieform $form, $values) {
// default back to where we came from
redirect('/webservice/admin/index.php?open=webservices_user');
$enabled = $values['enabled'] ? 0 : 1;
set_config('webservice_requester_enabled', $enabled);
// Don't reload the page if this was submitted via ajax.
if (param_boolean('ajax')) {
exit;
}
redirect('/webservice/admin/index.php');
}
/**
* Form layout for webservices master switch fieldset
*
* @return pieforms $element array
* Pieform for the master switch that controls whether Mahara will
* be a webservices provider (i.e. allow incoming webservices requests
* from other systems.)
*/
function webservices_master_switch_form() {
function webservice_provider_enabled_form() {
// enable/disable webservices completely
$enabled = (get_config('webservice_enabled') || 0);
$enabled = (get_config('webservice_provider_enabled') || 0);
$element = array(
'type' => 'html',
'value' =>
pieform(
array(
'name' => 'activate_webservices',
'name' => 'webservice_provider_enabled_form',
'elementclasses' => false,
'class' => 'form-switch',
'successcallback' => 'activate_webservices_submit',
'successcallback' => 'webservice_provider_enabled_submit',
'renderer' => 'div',
'jsform' => false,
'checkdirtychange' => false,
......@@ -322,7 +349,7 @@ function webservices_master_switch_form() {