Commit 2b21a6cc authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review
Browse files

Merge "Bug 1560778: Modal window for institution auth config"

parents 7fefd39f 3c396f54
......@@ -9,20 +9,17 @@
*
*/
define('INTERNAL', 1);
define('JSON', 1);
define('ADMIN', 1);
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
require_once(get_config('docroot') . '/lib/htmloutput.php');
define('MENUITEM', 'manageinstitutions/institutions');
define('TITLE', get_string('institutions', 'admin'));
$institution = param_variable('i');
$plugin = param_variable('p');
$add = param_boolean('add');
$edit = param_boolean('edit');
$json = param_boolean('j');
$instanceid = param_variable('id', 0);
define('TITLE', get_string($plugin . 'config', 'auth.' . $plugin));
// IF WE'RE EDITING OR CREATING AN AUTHORITY:
if ($institution && $plugin) {
$classname = 'PluginAuth' . ucfirst(strtolower($plugin));
......@@ -34,16 +31,6 @@ if ($institution && $plugin) {
// We've been asked to add an instance of an auth plugin that has no
// config options. We've been called by an AJAX request, so we just
// add the instance and generate an acknowledgement.
// The session key has not been checked yet, because this page doesn't
// define JSON
try {
form_validate(param_alphanum('sesskey', null));
}
catch (UserException $e) {
json_reply(true, $e->getMessage());
}
$authinstance = new stdClass();
// Get the auth instance with the highest priority number (which is
......@@ -67,25 +54,58 @@ if ($institution && $plugin) {
}
$form = call_static_method($classname, 'get_instance_config_options', $institution, $instanceid);
if (isset($form['error'])) {
json_reply(false, array('pluginname' => strtolower($plugin),
'html' => $form['error'])
);
exit;
}
$form['name'] = 'auth_config';
$form['action'] = get_config('wwwroot') . 'admin/users/addauthority.php';
$form['plugintype'] = 'auth';
$form['pluginname'] = strtolower($plugin);
$form['jsform'] = true;
$form['jssuccesscallback'] = 'authlist_success';
$form['jserrorcallback'] = 'authlist_error';
$form['elements']['i'] = array('type' => 'hidden', 'value' => $institution);
$form['elements']['p'] = array('type' => 'hidden', 'value' => $plugin);
$form['elements']['add'] = array('type' => 'hidden', 'value' => $add);
$form['elements']['edit'] = array('type' => 'hidden', 'value' => $edit);
$form['elements']['id'] = array('type' => 'hidden', 'value' => $instanceid);
$form['elements']['submit'] = array(
'type' => 'submitcancel',
'class' => 'btn-primary',
'value' => array(get_string('submit'), get_string('cancel')),
'goto' => get_config('wwwroot') . 'admin/users/institutions.php?i=' . $institution
'goto' => get_config('wwwroot') . 'admin/users/institutions.php?i=' . $institution,
);
$form = pieform($form);
$smarty = smarty();
if ($add) {
$smarty->assign('PAGETITLE', get_string('addauthority', 'auth'));
} else {
$smarty->assign('PAGETITLE', get_string('editauthority', 'auth'));
$pieform = pieform_instance($form);
$html = $pieform->build();
// TODO: The hacky code to extract the Javascript from the Pieforms has been
// copy-pasted from BlockInstance->build_configure_form(). At some point we should
// refactor it into shared code.
//
// We probably need a new version of $pieform->build() that separates out the js
// Temporary evil hack:
if (preg_match('/<script type="(text|application)\/javascript">(new Pieform\(.*\);)<\/script>/', $html, $matches)) {
$js = "var pf_{$form['name']} = " . $matches[2] . "pf_{$form['name']}.init();";
}
$smarty->assign('auth_imap_form', $form);
else if (preg_match('/<script>(new Pieform\(.*\);)<\/script>/', $html, $matches)) {
$js = "var pf_{$form['name']} = " . $matches[1] . "pf_{$form['name']}.init();";
}
else {
$js = '';
}
json_reply(
false,
array(
'html' => $html,
'javascript' => $js,
'pluginname' => strtolower($plugin),
)
);
}
function auth_config_validate(Pieform $form, $values) {
......@@ -94,9 +114,10 @@ function auth_config_validate(Pieform $form, $values) {
try {
$values = call_static_method($classname, 'validate_instance_config_options', $values, $form);
} catch (Exception $e) {
}
catch (Exception $e) {
if (!$form->has_errors()) {
$form->set_error('instancename', "An unknown error occurred while processing this form");
$form->json_reply(PIEFORM_ERR, "An unknown error occurred while processing this form");
}
}
}
......@@ -109,51 +130,13 @@ function auth_config_submit(Pieform $form, $values) {
safe_require('auth', strtolower($plugin));
$values = call_static_method($classname, 'save_instance_config_options', $values, $form);
redirect(get_config('wwwroot') . 'admin/users/institutions.php?i=' . $values['institution']);
$form->json_reply(
PIEFORM_OK,
array(
'id' => $values['instance'],
'name' => $values['instancename'],
'authname' => $values['authname'],
'new' => (int) array_key_exists('create', $values) && $values['create']
)
);
}
$js = <<<EOF
jQuery(function($) {
function authloginmsgVisibility() {
// If Parent authority is 'None'
if ($('#auth_config_parent').val() != 0) {
$('#auth_config_authloginmsg_container').addClass('d-none');
}
else {
$('#auth_config_authloginmsg_container').removeClass('d-none');
}
}
var ssoAllOptions = {
'updateuserinfoonlogin': 'theyssoin',
'weautocreateusers': 'theyssoin',
'theyautocreateusers': 'wessoout',
'weimportcontent': 'theyssoin'
};
function updateSsoOptions() {
var current = $('#auth_config_ssodirection').val();
for (var opt in ssoAllOptions) {
if (ssoAllOptions[opt] == current) {
$('#auth_config_' + opt + '_container').removeClass('d-none');
}
else {
$('#auth_config_' + opt + '_container').addClass('d-none');
}
}
}
if ($('#auth_config_parent').length) {
$('#auth_config_parent').on('change', authloginmsgVisibility);
authloginmsgVisibility();
}
if ($('#auth_config_ssodirection').length) {
$('#auth_config_ssodirection').on('change', updateSsoOptions);
updateSsoOptions();
}
});
EOF;
$institution = get_record('institution', 'name', $institution);
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->assign('SUBSECTIONHEADING', $institution->displayname);
$smarty->display('admin/users/addauthority.tpl');
......@@ -254,7 +254,6 @@ if ($institution || $add) {
}
$inuse = implode(',',$inuserecords);
}
$authtypes = auth_get_available_auth_types($institution);
}
else {
$data = new stdClass();
......@@ -277,8 +276,6 @@ if ($institution || $add) {
$data->commentsortorder = 'earliest';
$data->commentthreaded = false;
$lockedprofilefields = array();
$authtypes = auth_get_available_auth_types();
}
$themeoptions = get_institution_themes($institution);
$themeoptions['sitedefault'] = '- ' . get_string('sitedefault', 'admin') . ' (' . $themeoptions[get_config('theme')] . ') -';
......@@ -353,12 +350,11 @@ if ($institution || $add) {
'type' => 'authlist',
'title' => get_string('authplugin', 'admin'),
'options' => $authinstances,
'authtypes' => $authtypes,
'instancearray' => $instancearray,
'instancestring' => $instancestring,
'institution' => $institution,
'help' => true,
'ignore' => count($authtypes) == 0 || $institution == ''
'ignore' => ($add)
);
}
......@@ -1303,10 +1299,9 @@ jQuery(function($) {
});
';
$smarty = smarty();
$smarty = smarty(array('tinymce'));
setpageicon($smarty, 'icon-university');
$smarty->assign('INLINEJAVASCRIPT', $themeoptionsjs);
$smarty->assign('institution_form', $institutionform);
$smarty->assign('instancestring', $instancestring);
......
......@@ -149,7 +149,9 @@ class PluginAuthImap extends PluginAuth {
if ($instance > 0) {
$current = get_records_array('auth_instance', 'id', $instance, 'priority ASC');
if ($current == false) {
throw new SystemException('Could not find data for auth instance '.$instance);
return array(
'error' => get_string('nodataforinstance1', 'auth', $instance)
);
}
$default = $current[0];
$current_config = get_records_menu('auth_instance_config', 'instance', $instance, '', 'field, value');
......
......@@ -1717,7 +1717,9 @@ class PluginAuthLdap extends PluginAuth {
if ($instance > 0) {
$default = get_record('auth_instance', 'id', $instance);
if ($default == false) {
throw new SystemException('Could not find data for auth instance ' . $instance);
return array(
'error' => get_string('nodataforinstance1', 'auth', $instance)
);
}
$current_config = get_records_menu('auth_instance_config', 'instance', $instance, '', 'field, value');
......
......@@ -19,7 +19,7 @@ $idp = param_variable('idp', null);
$data = new stdClass();
if (file_exists(AuthSaml::prepare_metadata_path($idp))) {
$rawxml = file_get_contents(AuthSaml::prepare_metadata_path($idp));
$data->metarefresh_metadata_url = Metarefresh::get_metadata_url($idp);
$data->metarefresh_metadata_url = Metarefresh::get_metadata_url($idp, true);
$data->metadata = $rawxml;
$data->error = false;
}
......
......@@ -993,15 +993,17 @@ class PluginAuthSaml extends PluginAuth {
public static function get_instance_config_options($institution, $instance = 0) {
if (!class_exists('SimpleSAML_XHTML_IdPDisco')) {
global $SESSION;
$SESSION->add_error_msg(get_string('errorssphpsetup', 'auth.saml'));
redirect(get_config('wwwroot') . 'admin/users/institutions.php?i=' . $institution);
return array(
'error' => get_string('errorssphpsetup', 'auth.saml')
);
}
if ($instance > 0) {
$default = get_record('auth_instance', 'id', $instance);
if ($default == false) {
throw new SystemException('Could not find data for auth instance ' . $instance);
return array(
'error' => get_string('nodataforinstance1', 'auth', $instance)
);
}
$current_config = get_records_menu('auth_instance_config', 'instance', $instance, '', 'field, value');
......@@ -1143,7 +1145,6 @@ EOF;
),
'metarefresh_metadata_url' => array(
'type' => 'text',
'size' => 100,
'title' => get_string('metarefresh_metadata_url', 'auth.saml'),
'rules' => array(
'required' => false,
......@@ -1532,12 +1533,14 @@ class Metarefresh {
/*
* Return all configured metadataurls for idps if any found
*/
public static function get_metadata_urls() {
public static function get_metadata_urls($viajson=false) {
$finalarr = array();
$sites = get_records_menu('auth_instance_config', 'field', 'institutionidpentityid', '', 'instance, value');
$urls = get_records_array('auth_instance_config', 'field', 'metarefresh_metadata_url', '', 'field, value, instance');
if ( ( !$sites || count($sites) <= 0 ) || ( !$urls || count($urls) <= 0 ) ) {
log_warn("Could not get any valid urls for metadata refresh url list", false, false);
if ($viajson === false) {
log_warn("Could not get any valid urls for metadata refresh url list", false, false);
}
return array();//could not get any valid urls to fetch metadata from
}
foreach($urls as $url) {
......@@ -1553,8 +1556,8 @@ class Metarefresh {
/*
* Given an IDP entity id, find the source url for it
*/
public static function get_metadata_url($idp) {
$sources = self::get_metadata_urls();
public static function get_metadata_url($idp, $viajson=false) {
$sources = self::get_metadata_urls($viajson);
if (isset($sources[$idp])) {
return $sources[$idp];
}
......
......@@ -651,12 +651,16 @@ class PluginAuthXmlrpc extends PluginAuth {
if ($instance > 0) {
$default = get_record('auth_instance', 'id', $instance);
if ($default == false) {
throw new SystemException(get_string('nodataforinstance', 'auth').$instance);
return array(
'error' => get_string('nodataforinstance1', 'auth', $instance)
);
}
$current_config = get_records_menu('auth_instance_config', 'instance', $instance, '', 'field, value');
if ($current_config == false) {
throw new SystemException('No config data for instance: '.$instance);
return array(
'error' => get_string('nodataforinstance1', 'auth', $instance)
);
}
foreach (self::$default_config as $key => $value) {
......
......@@ -30,7 +30,7 @@ $string['xmlrpcserverurl'] = 'XML-RPC server URL';
$string['ipaddress'] = 'IP address';
$string['shortname'] = 'Short name for your site';
$string['name'] = 'Site name';
$string['nodataforinstance'] = 'Could not find data for authentication instance ';
$string['nodataforinstance1'] = 'Could not find data for authentication instance "%s".';
$string['authname'] = 'Authority name';
$string['weautocreateusers'] = 'We auto-create users';
$string['theyautocreateusers'] = 'They auto-create users';
......
......@@ -35,7 +35,7 @@ function pieform_element_authlist(Pieform $form, $element) {
}
if (is_array($value) && count($value)) {
$smarty->assign('authtypes', $value['authtypes']);
$smarty->assign('authtypes', auth_get_available_auth_types($value['institution']));
$smarty->assign('instancelist', $value['instancelist']);
$smarty->assign('instancestring', implode(',',$value['instancearray']));
$smarty->assign('default', $value['default']);
......@@ -43,10 +43,6 @@ function pieform_element_authlist(Pieform $form, $element) {
}
$smarty->assign('name', $element['name']);
$smarty->assign('cannotremove', json_encode(get_string('cannotremove', 'auth')));
$smarty->assign('cannotremoveinuse', json_encode(get_string('cannotremoveinuse', 'auth')));
$smarty->assign('saveinstitutiondetailsfirst', json_encode(get_string('saveinstitutiondetailsfirst', 'auth')));
$smarty->assign('noauthpluginconfigoptions', json_encode(get_string('noauthpluginconfigoptions', 'auth')));
return $smarty->fetch('form/authlist.tpl');
}
......@@ -71,24 +67,54 @@ function pieform_element_authlist_get_value(Pieform $form, $element) {
}
$value['instancelist'] = $element['options'];
$value['authtypes'] = $element['authtypes'];
$value['authtypes'] = auth_get_available_auth_types($element['institution']);
$value['instancePriority'] = $element['instancestring'];
$value['institution'] = $element['institution'];
return $value;
}
/**
* Javascript to load libraries used by all authlist elements on the page
*/
function pieform_element_authlist_js() {
return <<<EOF
$return = <<<EOF
// Load strings used by the authlist Pieforms element
if (strings !== undefined) {
EOF;
$jsstrings = array(
array('cannotremove', 'auth'),
array('cannotremoveinuse', 'auth'),
array('saveinstitutiondetailsfirst', 'auth'),
array('noauthpluginconfigoptions', 'auth'),
);
foreach ($jsstrings as $stringdata) {
list($tag, $section) = $stringdata;
$return .= ' strings["' . $tag . '"] = ' . json_encode(get_raw_string($tag, $section)) . ";\n";
}
$return .= <<<EOF
}
// Load methods used by the authlist and its modal
PieformManager.loadPlugin('element', 'authlist');
// Since this menu is just a dummy selector, don't let it trigger the form change checker.
jQuery(document).on('pieform_postinit', function(event, form) {
jQuery('form[name=' + form.data.name + ']').find('select#dummySelect').off('change.changechecker');
var formid = jQuery('select#authlistDummySelect').closest('form').attr('id');
PieformManager.connect('onload', formid, function(pformid) {
var selector = 'select#authlistDummySelect';
if (pformid) {
selector = 'form#' + pformid + ' ' + selector;
}
jQuery(selector).off('change.changechecker');
});
EOF;
return $return;
}
function pieform_element_authlist_get_headdata() {
$result = '<script>' . pieform_element_authlist_js() . "</script>";
function pieform_element_authlist_get_headdata($element) {
$result = '<script type="application/javascript">' . pieform_element_authlist_js() . "</script>";
return array($result);
}
/**
* Javascript for the authlist Pieform element
*
* @package mahara
* @subpackage pieform.authlist
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
(function (PieformAuthlist) {
"use strict";
// Public methods
/**
* Handler for the user clicking the "edit" button next to an auth instance
* @param id
* @param plugin
*/
PieformAuthlist.edit_auth = function(id, plugin) {
if (requiresConfig(plugin)) {
sendjsonrequest(
config.wwwroot + 'admin/users/addauthority.php',
{
'id': id,
'edit': 1,
'i': get_institution(),
'p': plugin,
'sesskey': config.sesskey,
},
'GET',
open_modal
);
dock.show(jQuery('#configureauthinstance-modal'), true, true);
}
else {
alert(get_string('noauthpluginconfigoptions'));
}
};
/**
* Move the auth instance up in the list
*
* @param id
*/
PieformAuthlist.move_up = function(id) {
var instanceArray = document.getElementById('instancePriority').value.split(',');
var outputArray = new Array();
for (var 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];
}
}
rebuildInstanceList(outputArray);
if (typeof formchangemanager !== 'undefined') {
var form = jQuery('div#instanceList').closest('form')[0];
formchangemanager.setFormState(form, FORM_CHANGED);
}
};
/**
* Move the auth instance down in the list
* @param id
*/
PieformAuthlist.move_down = function(id) {
var instanceArray = document.getElementById('instancePriority').value.split(',');
var outputArray = new Array();
for (var 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];
}
}
rebuildInstanceList(outputArray);
if (typeof formchangemanager !== 'undefined') {
var form = jQuery('div#instanceList').closest('form')[0];
formchangemanager.setFormState(form, FORM_CHANGED);
}
};
/**
* Remove auth instance from the list
*
* @param id
* @returns {Boolean}
*/
PieformAuthlist.remove_auth = function(id) {
var instanceArray = arrayIze('instancePriority');
var deleteArray = arrayIze('deleteList');
var inuseArray = arrayIze('institution_inuse');
if (instanceArray.length == 1) {
alert(get_string('cannotremove'));
return false;
}
for (var i = 0; i < inuseArray.length; i++) {
if (id == inuseArray[i]) {
alert(get_string('cannotremoveinuse'));
return false;
}
}
for (var i = 0; i < instanceArray.length; i++) {
if (instanceArray[i] == id) {
instanceArray.splice(i, 1);
deleteArray.push(id);
jQuery('#instanceList div#instanceDiv' + id).remove();
}
}
document.getElementById('deleteList').value = deleteArray.join(',');
rebuildInstanceList(instanceArray);
if (typeof formchangemanager !== 'undefined') {
var form = jQuery('div#instanceList').closest('form')[0];
formchangemanager.setFormState(form, FORM_CHANGED);
}
};
/**
* Display a newly created auth instance, in the auth instance list
*
* @param id
* @param name
* @param authname
*/
PieformAuthlist.insert_auth = function(id, name, authname) {
var instanceArray;
var newDiv = '<div class="authInstance" id="instanceDiv'+id+'"> ' +
'<span class="authitem">' +
'<label class="authLabel"><a href="" onclick="PieformAuthlist.edit_auth('+id+',\''+authname+'\'); return false;">'+name+'</a></label> ' +
'<span class="authIcons" id="arrows'+id+'"></span></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);
jQuery('#messages').empty();
}
/**
* Handler for the user clicking the "add" button
* @returns {Boolean}
*/
PieformAuthlist.create_auth = function() {
var authlistDummySelect = jQuery('#authlistDummySelect');
var selectedPlugin = authlistDummySelect.val();
var institution = get_institution();
if (institution.length == 0) {
alert('saveinstitutiondetailsfirst');
return false;
}