Commit aa743c03 authored by Piers Harding's avatar Piers Harding Committed by Aaron Wells
Browse files

Bug 1393536: client connection manager

* added new client connection manager screens
* added client connection manager backend

behatnotneeded

Change-Id: Iac103616c7a9cd68cc94ea301a4cb808fe090669
parent 9fb9d801
......@@ -16,6 +16,7 @@ $string['title'] = 'Web services';
$string['description'] = 'Web services-only users authenticated against Mahara\'s database';
$string['webservicesconfig'] = 'Configuration';
$string['webservicesconfigdesc'] = 'Here you can set up the varying web services rules and enable or disable them.';
$string['webserviceconnectionsconfigdesc'] = 'Setup the connection objects that registered plugins can use for communication with external systems';
$string['completeregistration'] = 'Complete registration';
$string['emailalreadytaken'] = 'This email address has already registered here';
$string['iagreetothetermsandconditions'] = 'I agree to the Terms and Conditions.';
......@@ -51,11 +52,43 @@ $string['usernameinvalidform'] = 'Usernames may contain letters, numbers and mos
$string['usernameinvalidadminform'] = 'Usernames may contain letters, numbers and most common symbols, and must be from 3 to 236 characters in length. Spaces are not allowed.';
$string['youmaynotregisterwithouttandc'] = 'You may not register unless you agree to abide by the <a href="terms.php">Terms and Conditions</a>.';
$string['pluginconnections'] = 'Plugin Connection Objects';
$string['pcdescription'] = 'Create connections connected to the Connection Objects of registered plugins.';
$string['addconnection'] = 'Add Client Connection';
$string['editconnection'] = 'Edit Client Connection';
$string['clientconnections'] = 'Client Connection';
$string['plugin'] = 'Connection Plugin';
$string['clienturl'] = 'Web Service URL';
$string['password'] = 'Password';
$string['parameters'] = 'Fixed Parameters to pass';
$string['certificate'] = 'XML-RPC Partner Certificate';
$string['enable'] = 'Connection enabled';
$string['json'] = 'JSON encoded';
$string['isfatal'] = 'Is fatal on error';
$string['type'] = 'Web Service Type';
$string['nameexists'] = "Name already in use";
$string['emptytoken'] = 'Token must be supplied';
$string['emptyuserpass'] = 'User and Password must be supplied';
$string['emptycert'] = 'Certificate must be supplied';
$string['header'] = 'Header Name';
$string['useheader'] = 'Put authentication in Header';
$string['invalidauthtypecombination'] = 'Invalid authentication type selected for %s';
$string['emptycertextended'] = 'When using certificate based auth you must also enter a token or username/password';
$string['emptyoauth'] = 'Consumer and Secret must be supplied for OAuth1.x';
$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['formatdate'] = '';
$string['protocolswitches'] = 'Switch protocols on or off';
$string['connectionsswitch'] = 'Switch managed client connections on or off';
$string['manage_protocols'] = 'Enable or disable protocols that are to be supported:';
$string['protocol'] = 'Protocol';
$string['rest'] = 'REST';
......@@ -95,6 +128,7 @@ $string['missingimplofmeth'] = 'Missing implementation method of "%s"';
$string['cannotfindimplfile'] = 'Cannot find file with external function implementation';
$string['apptokens'] = 'Application connections';
$string['connections'] = 'Connection Manager';
$string['servicetokens'] = 'Manage service access tokens';
$string['tokens'] = 'Service access tokens';
$string['users'] = 'Service users';
......@@ -162,6 +196,9 @@ $string['wsdoc'] = 'Web services documentation';
$string['testclient'] = 'Web services test client';
$string['tokenauth'] = 'Token';
$string['userauth'] = 'User';
$string['certauth'] = 'Certificate';
$string['wsseauth'] = 'WSSE';
$string['oauth1auth'] = 'OAuth1.x';
$string['authtype'] = 'Authentication type';
$string['sauthtype'] = 'AuthType';
$string['enterparameters'] = 'Enter function parameters';
......@@ -176,6 +213,7 @@ $string['unabletoruntestclient'] = 'Web service test client needs to be run unde
$string['accesstokens'] = 'OAuth access tokens';
$string['notokens'] = 'You have no application tokens';
$string['oauth'] = 'OAuth';
$string['oauth1'] = 'OAuth1.x';
$string['oauthv1sregister'] = 'OAuth service registration';
$string['userapplications'] = 'OAuth consumer keys';
$string['accessto'] = 'Access to';
......
......@@ -707,7 +707,7 @@
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="usr,expiry" />
<KEY NAME="foreign" TYPE="foreign" FIELDS="usr" REFTABLE="usr" REFFIELDS="id" />
</KEYS>
</KEYS>
</TABLE>
<TABLE NAME="view_layout_columns">
<FIELDS>
......@@ -739,7 +739,7 @@
<FIELD NAME="columns" TYPE="int" LENGTH="10" NOTNULL="true"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="rowfk" TYPE="foreign" FIELDS="viewlayout" REFTABLE="view_layout" REFFIELDS="id"/>
<KEY NAME="columnsfk" TYPE="foreign" FIELDS="columns" REFTABLE="view_layout_columns" REFFIELDS="id"/>
</KEYS>
......@@ -962,7 +962,7 @@
</KEYS>
</TABLE>
<!-- site content stuff -->
<!--
<!--
<TABLE NAME="site_file">
</TABLE>
-->
......@@ -984,7 +984,7 @@
-->
</KEYS>
</TABLE>
<TABLE NAME="site_content">
<TABLE NAME="site_content">
<FIELDS>
<FIELD NAME="name" TYPE="char" LENGTH="50" NOTNULL="true" />
<FIELD NAME="content" TYPE="text" NOTNULL="true" />
......@@ -1326,5 +1326,40 @@
<KEY NAME="groupfk" TYPE="foreign" FIELDS="group" REFTABLE="group" REFFIELDS="id" />
</KEYS>
</TABLE>
<TABLE NAME="client_connections_institution">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="plugintype" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Plugin type eg: notification"/>
<FIELD NAME="pluginname" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Plugin type eg: log"/>
<FIELD NAME="priority" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="class" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Plugin class name"/>
<FIELD NAME="connection" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="connection name"/>
<FIELD NAME="institution" TYPE="char" LENGTH="255" NOTNULL="true" />
<FIELD NAME="url" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" COMMENT="URL for the web service call"/>
<FIELD NAME="username" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Username for the web service call"/>
<FIELD NAME="password" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Password for the web service call"/>
<FIELD NAME="consumer" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="OAuth Consumer Key for the web service call"/>
<FIELD NAME="secret" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="OAuth Secret for the web service call"/>
<FIELD NAME="token" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Auth token for the web service call"/>
<FIELD NAME="useheader" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
<FIELD NAME="header" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="HTTP Header name if useheader"/>
<FIELD NAME="certificate" TYPE="text" LENGTH="small" NOTNULL="false" COMMENT="Auth certificate for the web service call"/>
<FIELD NAME="parameters" TYPE="text" LENGTH="small" NOTNULL="false" COMMENT="Additional parameters for the web service call"/>
<FIELD NAME="type" TYPE="char" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="authtype" TYPE="char" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="json" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
<FIELD NAME="enable" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
<FIELD NAME="isfatal" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
<FIELD NAME="version" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="institution" TYPE="foreign" FIELDS="institution" REFTABLE="institution" REFFIELDS="name"/>
</KEYS>
<INDEXES>
<INDEX NAME="connectionk" UNIQUE="true" FIELDS="name,class,connection,institution" COMMENT="the connections can be repeated but the name must be unique for a given type and institution"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
......@@ -4522,5 +4522,39 @@ function xmldb_core_upgrade($oldversion=0) {
rmdirr(get_config('dataroot') . 'smarty');
}
if ($oldversion < 2016070800) {
log_debug('Add client_connections_institution table');
$table = new XMLDBTable('client_connections_institution');
$table->addFieldInfo('id', XMLDB_TYPE_INTEGER, 10, null, XMLDB_NOTNULL, XMLDB_SEQUENCE);
$table->addFieldInfo('name', XMLDB_TYPE_CHAR, 255, false, XMLDB_NOTNULL);
$table->addFieldInfo('plugintype', XMLDB_TYPE_CHAR, 255, false, XMLDB_NOTNULL);
$table->addFieldInfo('pluginname', XMLDB_TYPE_CHAR, 255, false, XMLDB_NOTNULL);
$table->addFieldInfo('priority', XMLDB_TYPE_INTEGER, 10, false, XMLDB_NOTNULL);
$table->addFieldInfo('class', XMLDB_TYPE_CHAR, 255, false, XMLDB_NOTNULL);
$table->addFieldInfo('connection', XMLDB_TYPE_CHAR, 255, false, XMLDB_NOTNULL);
$table->addFieldInfo('institution', XMLDB_TYPE_CHAR, 255, false, XMLDB_NOTNULL);
$table->addFieldInfo('url', XMLDB_TYPE_TEXT, 'small', false, XMLDB_NOTNULL);
$table->addFieldInfo('username', XMLDB_TYPE_CHAR, 255, false);
$table->addFieldInfo('password', XMLDB_TYPE_CHAR, 255, false);
$table->addFieldInfo('consumer', XMLDB_TYPE_CHAR, 255, false);
$table->addFieldInfo('secret', XMLDB_TYPE_CHAR, 255, false);
$table->addFieldInfo('token', XMLDB_TYPE_CHAR, 255, false);
$table->addFieldInfo('header', XMLDB_TYPE_CHAR, 255, false);
$table->addFieldInfo('useheader', XMLDB_TYPE_INTEGER, 1, false, XMLDB_NOTNULL, null, null, null, 1);
$table->addFieldInfo('certificate', XMLDB_TYPE_TEXT, 'small', false);
$table->addFieldInfo('parameters', XMLDB_TYPE_TEXT, 'small', false);
$table->addFieldInfo('type', XMLDB_TYPE_CHAR, 10, false, XMLDB_NOTNULL, null, null, null, 2);
$table->addFieldInfo('authtype', XMLDB_TYPE_CHAR, 10, false, XMLDB_NOTNULL);
$table->addFieldInfo('json', XMLDB_TYPE_INTEGER, 1, false, XMLDB_NOTNULL, null, null, null, 1);
$table->addFieldInfo('enable', XMLDB_TYPE_INTEGER, 1, false, XMLDB_NOTNULL, null, null, null, 1);
$table->addFieldInfo('isfatal', XMLDB_TYPE_INTEGER, 1, false, XMLDB_NOTNULL, null, null, null, 1);
$table->addFieldInfo('version', XMLDB_TYPE_CHAR, 255, false);
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->addIndexInfo('connectionk', XMLDB_INDEX_UNIQUE, array('name', 'class', 'connection', 'institution'));
$table->addKeyInfo('institution', XMLDB_KEY_FOREIGN, array('institution'), 'institution', array('name'));
create_table($table);
clear_menu_cache();
}
return $status;
}
......@@ -1916,6 +1916,44 @@ interface IPlugin {
public static function get_plugintype_name();
}
/**
* defines for web services types and authentication
*
*
*/
define('WEBSERVICE_TYPE_SOAP', 'soap');
define('WEBSERVICE_TYPE_XMLRPC', 'xmlrpc');
define('WEBSERVICE_TYPE_REST', 'rest');
define('WEBSERVICE_TYPE_OAUTH1', 'oauth1');
define('WEBSERVICE_AUTH_USERPASS', 'user');
define('WEBSERVICE_AUTH_TOKEN', 'token');
define('WEBSERVICE_AUTH_CERT', 'cert');
define('WEBSERVICE_AUTH_WSSE', 'wsse');
/**
* Generate an HTTP context object
*
* @param string $url
* @return object - stream context object
*/
function webservice_create_context($url) {
$hostname = parse_url($url, PHP_URL_HOST);
$context = array('http' => array ('method' => 'POST',
'request_fulluri' => true,),
);
if (get_config('disablesslchecks')) {
$context['ssl'] = array('verify_host' => false,
'verify_peer' => false,
'verify_peer_name' => false,
'SNI_server_name' => $hostname,
'SNI_enabled' => true,);
}
$context = stream_context_create($context);
return $context;
}
/**
* Base class for all plugintypes.
*/
......@@ -1958,6 +1996,190 @@ abstract class Plugin implements IPlugin {
return array();
}
/**
* This function returns an array of client connection by unique name.
*
* The return value should be array of objects. Each object should have these fields:
*
* - connection: The name of the client connection handle.
* - name: The descriptive name of the client connection for display purposes
* - version: A version required for the connection
* - notes: descriptive text that developer might want to show user
* - type: Protocol type required eg: WEBSERVICE_CLIENT_TYPE_SOAP
* - isfatal: Should an error be fatal
*
* @return array
*/
public static function define_webservice_connections() {
return array();
}
/**
* This function returns an array of client connection records.
*
* @param array $institutions the institutions for the context of selecting
* the client connections
*
* @return array
*/
public static function calculate_webservice_connections($institutions) {
$me = get_called_class();
$connection_defs = call_user_func($me . '::define_webservice_connections');
$connections = array();
foreach ($connection_defs as $def) {
if (isset($def['connection'])) {
$cname = $def['connection'];
if ($results = get_records_sql_assoc(
'SELECT cci.*
FROM client_connections_institution AS cci
WHERE cci.class = ? AND
cci.connection = ? AND
cci.institution IN ('.join(',', array_map('db_quote', $institutions)).') AND enable = 1', array($me, $cname))
) {
foreach ($results as $c) {
$c->version = $def['version'];
$c->connectorname = $def['name'];
$connections[]= $c;
}
}
}
}
return $connections;
}
/**
* This function returns an array of client connections.
*
* @param object $user the user for the context of selecting the client connections
*
* @return array
*/
public static function get_webservice_connections($user=null) {
global $USER;
// are web service connections enabled?
if (!get_config('webservice_connections_enabled')) {
error_log('disabled');
return array();
}
require_once(get_config('docroot') . 'webservice/lib.php');
$userinstitutions = ($user == null ? $USER->get('institutions') : load_user_institutions($user->id));
$userinstitutions[]= 'mahara';
$cdefs = self::calculate_webservice_connections($userinstitutions);
$connections = array();
foreach ($cdefs as $c) {
$client = null;
$auth = array();
$authtype = null;
if (!empty($c->token)) {
$authtype = 'token';
if ($c->useheader) {
$auth['header'] = (empty($c->header) ? 'Authorization' : $c->header.": ".$c->token);
}
else {
if (strpos($c->token, '=')) {
list($k, $v) = explode('=', $c->token);
$auth[$k] = $v;
}
else {
$auth['wstoken'] = $c->token;
}
}
}
else if (!empty($c->username) && !empty($c->password) ) {
$authtype = 'user';
if (strpos($c->username, '=')) {
list($k, $v) = explode('=', $c->token);
$auth[$k] = $v;
}
else {
$auth['wsusername'] = $c->username;
}
if (strpos($c->password, '=')) {
list($k, $v) = explode('=', $c->password);
$auth[$k] = $v;
}
else {
$auth['wspassword'] = $c->password;
}
}
// other static parameters - one per line
// error_log('connection: '.var_export($c, true));
if (!empty($c->parameters)) {
$params = explode("\n", $c->parameters);
foreach ($params as $p) {
if (strpos($p, '=')) {
list($k, $v) = explode('=', $p);
$auth[$k] = $v;
}
}
}
switch ($c->type) {
case WEBSERVICE_TYPE_SOAP:
require_once(get_config('docroot') . "webservice/soap/lib.php");
libxml_disable_entity_loader(true);
if ($c->authtype == WEBSERVICE_AUTH_WSSE) {
//force SOAP synchronous mode
$client = new webservice_soap_client($c->url,
$auth,
array("features" => SOAP_WAIT_ONE_WAY_CALLS,
'stream_context' => webservice_create_context($c->url),));
//when function return null
$wsseSoapClient = new webservice_soap_client_wsse(array($client, '_doRequest'), $client->wsdlfile, $client->getOptions());
$wsseSoapClient->__setUsernameToken($c->username, $c->password);
$client->setSoapClient($wsseSoapClient);
}
else {
//force SOAP synchronous mode
$client = new webservice_soap_client($c->url,
$auth,
array("features" => SOAP_WAIT_ONE_WAY_CALLS,
'stream_context' => webservice_create_context($c->url),));
}
$client->setWsdlCache(false);
break;
case WEBSERVICE_TYPE_XMLRPC:
require_once(get_config('docroot') . "webservice/xmlrpc/lib.php");
error_log('xmlrpc auth: '.var_export($auth, true));
$client = new webservice_xmlrpc_client($c->url, $auth);
if ($c->authtype == WEBSERVICE_AUTH_CERT) {
$client->setCertificate($c->certificate);
}
break;
case WEBSERVICE_TYPE_REST:
require_once(get_config('docroot') . "webservice/rest/lib.php");
if ($c->authtype == WEBSERVICE_TYPE_OAUTH1) {
$client = new webservice_rest_client($c->url, $auth, 'oauth', $c->json);
$client->set_2legged($c->consumer, $c->secret);
}
else {
$client = new webservice_rest_client($c->url, $auth, $c->authtype, $c->json);
}
break;
default:
error_log("Unknown WEBSERVICE_TYPE: ".$c->type);
break;
}
if ($client) {
$client->set_connection($c);
$connections[]= $client;
}
}
syslog(LOG_INFO, "Mahara triggered get_webservice_connections");
error_log("Mahara triggered get_webservice_connections");
return $connections;
}
/**
* This function will be run after every upgrade to the plugin.
......
......@@ -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 = 2016070700;
$config->version = 2016070800;
$config->series = '16.10';
$config->release = '16.10dev';
$config->minupgradefrom = 2012080604;
......
{include file="header.tpl"}
<div class="panel panel-default">
<h3 class="panel-heading">{str tag="clientconnections" section="auth.webservice"}</h3>
<div class="panel-body">
{$form|safe}
</div>
</div>
{include file="footer.tpl"}
<script type="application/javascript">
function move_up(id) {
instanceArray = document.getElementById('instancePriority').value.split(',');
var outputArray = new Array();
for(i = instanceArray.length - 1; i >= 0; i--) {
if(instanceArray[i] == id) {
outputArray[i] = instanceArray[i-1];
outputArray[i-1] = instanceArray[i];
--i;
} else {
outputArray[i] = instanceArray[i];
}
}
sendjsonrequest('{{$WWWROOT}}webservice/admin/connections.php', {'i': '{{$institution}}', 'ids': outputArray.join(','), 'reorder': 1, 'j': 1}, 'GET', function (data) {
rebuildInstanceList(outputArray);
});
return false;
}
function move_down(id) {
instanceArray = document.getElementById('instancePriority').value.split(',');
var outputArray = new Array();
for(i = 0; i < instanceArray.length; i++) {
if(instanceArray[i] == id) {
outputArray[i+1] = instanceArray[i];
outputArray[i] = instanceArray[i+1];
++i;
} else {
outputArray[i] = instanceArray[i];
}
}
sendjsonrequest('{{$WWWROOT}}webservice/admin/connections.php', {'i': '{{$institution}}', 'ids': outputArray.join(','), 'reorder': 1, 'j': 1}, 'GET', function (data) {
rebuildInstanceList(outputArray);
});
return false;
}
function rebuildInstanceList(outputArray) {
var displayArray = new Array();
var instanceListDiv = document.getElementById('instanceList');
// Take each auth instance div, remove its span tag (containing arrow links) and clone it
// adding the clone to the displayArray list
for (i = 0; i < outputArray.length; i++) {
var myDiv = document.getElementById('instanceDiv' + outputArray[i]);
replaceChildNodes(getFirstElementByTagAndClassName('span', 'authIcons', 'instanceDiv' + outputArray[i]));
displayArray.push(myDiv.cloneNode(true));
}
emptyThisNode(instanceListDiv);
for(i = 0; i < displayArray.length; i++) {
if(displayArray.length > 1) {
if (i + 1 != displayArray.length) {
getFirstElementByTagAndClassName('span', 'authIcons', displayArray[i]).innerHTML += '<a class="btn btn-link text-midtone" href="" onclick="move_down('+outputArray[i]+'); return false;"><span class="icon icon-long-arrow-down" role="presentation" aria-hidden="true"></span><span class="sr-only">'+get_string('moveitemdown')+'</span></a>'+"\n";
}
if(i != 0) {
getFirstElementByTagAndClassName('span', 'authIcons', displayArray[i]).innerHTML += '<a class="btn btn-link text-midtone" href="" onclick="move_up('+outputArray[i]+'); return false;"><span class="icon icon-long-arrow-up" role="presentation" aria-hidden="true"></span><span class="sr-only">'+get_string('moveitemup')+'</span></a>'+"\n";
}
}
getFirstElementByTagAndClassName('span', 'authIcons', displayArray[i]).innerHTML += '<a class="btn btn-default btn-sm" href="" onclick="removeConnection('+outputArray[i]+'); return false;"><span class="icon icon-trash icon-lg text-danger" role="presentation" aria-hidden="true"></span><span class="sr-only">'+get_string('deleteitem')+'</span></a>'+"\n";
instanceListDiv.appendChild(displayArray[i]);
}
document.getElementById('instancePriority').value = outputArray.join(',');
}
function arrayIze(id) {
var thing = document.getElementById(id).value;
if (thing == '') {
return new Array();
}
return thing.split(',');
}
function removeConnection(id) {
instanceArray = arrayIze('instancePriority');
deleteArray = arrayIze('deleteList');
sendjsonrequest('{{$WWWROOT}}webservice/admin/addconnection.php', {'i': '{{$institution}}', 'id': id, 'delete': 1, 'j': 1}, 'GET', function (data) {
for(i = 0; i < instanceArray.length; i++) {
if(instanceArray[i] == id) {
instanceArray.splice(i, 1);
deleteArray.push(id);
var instances = jQuery('#instanceDiv'+id);
instances.remove(0);
}
}
rebuildInstanceList(instanceArray);
document.getElementById('deleteList').value = deleteArray.join(',');
});
return false;
}
function emptyThisNode(node) {
while(node.hasChildNodes()) {
node.removeChild(node.childNodes[0]);
}
}
function addinstance() {
var selectedPlugin = document.getElementById('dummySelect').value;
var institution = '{{$institution}}';
window.open('{{$WWWROOT}}webservice/admin/addconnection.php?add=1&i={{$institution}}&p=' + selectedPlugin, 'addinstance', 'height=600,width=800,screenx=250,screenY=200,scrollbars=1');
return;
}
function editinstance(id, plugin) {
// if (requiresConfig(plugin)) {
window.open('addconnection.php?id='+id+'&edit=1&i={{$institution}}&p=' + plugin, 'editinstance', 'height=520,width=550,screenx=250,screenY=200,scrollbars=1');
return;
}
function addConnection(id, name, connectionname) {
var newDiv = '<div class="authInstance" id="instanceDiv'+id+'"> '+
'<label class="authLabel"><a href="" onclick="editinstance('+id+',\''+connectionname+'\'); return false;">'+name+'</a></label> '+
'<span class="authIcons" id="arrows'+id+'"></span> </div>';
document.getElementById('instanceList').innerHTML += newDiv;
if(document.getElementById('instancePriority').value.length) {
instanceArray = document.getElementById('instancePriority').value.split(',');
} else {
instanceArray = new Array();
}
instanceArray.push(id);
rebuildInstanceList(instanceArray);
if (typeof formchangemanager !== 'undefined') {