Commit 3c396f54 authored by Aaron Wells's avatar Aaron Wells Committed by Robert Lyon

Bug 1560778: Modal window for institution auth config

Have rebased this and got it working by removing old mochikit stuff

behatnotneeded

Change-Id: Id4bbd0d08d6b743fdec426f27e41a2fbb9857651
parent 308fae17
......@@ -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);
}
This diff is collapsed.
......@@ -36,7 +36,6 @@ var PieformManager = (function($) {
this.init = function() {
self.connect('onload', null, self.setFocus);
self.signal('onload', null);
};
/**
......@@ -84,8 +83,7 @@ var PieformManager = (function($) {
'type': 'application/javascript',
'src' : self.pieformPath + type + 's/' + name + '.js'
});
script.append(self.head);
$('head').append(script);
self.loadCache[type][name] = 1;
};
......@@ -153,9 +151,7 @@ var Pieform = (function($) {
self.connectSubmitButtons();
// Hook for pieform elements that need to execute Javascript
// *after* the Pieform has been initialized.
$(document).triggerHandler('pieform_postinit', self);
PieformManager.signal('onload', self.data.name);
};
this.processForm = function(e) {
......
......@@ -516,8 +516,27 @@
margin-bottom: 20px;
}
#auth_config_institutionidp {
width: 90%;
#configureauthinstance-modal {
.modal-body textarea.under-label,
.modal-body .under-label-help.wysiwyg .mce-tinymce {
width: calc(100% - 30px) !important;
}
.modal-body .form-group.text {
label {
max-width: calc(50% - 30px);
}
input[type="text"] {
max-width: 50%;
}
}
.modal-body .form-group.password {
label {
max-width: calc(50% - 30px);
}
input[type="password"] {
max-width: 50%;
}
}
}
.defaultskin {
......
{include file="header.tpl"}
<div class="card">
<h3 class="card-header">{str tag="adminauthorities" section="admin"}</h3>
<div class="card-body">
{$auth_imap_form|safe}
</div>
</div>
{include file="footer.tpl"}
......@@ -19,17 +19,20 @@ Scenario: Creating an institution (selenium test)
Then I should see "Institution added successfully"
# Adding some authentication options
And I select "webservice" from "dummySelect"
And I scroll to the base of id "dummySelect"
And I select "webservice" from "authlistDummySelect"
And I scroll to the base of id "authlistDummySelect"
And I press "Add"
And I press "Submit"
# Moving authentication option
# Moving authentication option upwards
And I click on "Edit" in "Institution One" row
And I scroll to the base of id "dummySelect"
And I scroll to the base of id "authlistDummySelect"
And I follow "Move up"
And I press "Submit"
# Removing the first authentication option
And I click on "Edit" in "Institution One" row
And I scroll to the base of id "authlistDummySelect"
And I click on "Delete" in "Web services" row
# Adding an institution logo
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment