Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 66 additions & 205 deletions core/plugins/authentication/shibboleth/assets/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,219 +22,80 @@ jQuery(function($) {
jQuery(function($) {
$('#jform_params_institutions-lbl').hide();

var prnt = $('.shibboleth'),
// control values are stored in a JSON string so they fit in the extensions table
serialized = $('.shibboleth input.serialized'),
// initialize from existing params
val = JSON.parse(serialized.val()),
// update hidden input to reflect form state
update = function() {
console.log('upd');
serialized.val(JSON.stringify(val));
console.log('update', serialized.val());
},
// update active idp list state
updateIdps = function() {
val.activeIdps = [];
var anyInvalid = false;
prnt.find('ul.active li').each(function(_, li) {
addedEntities = {}
var idp = {}, thisInvalid = false;
// copy form data to 'val'
$(li).find('input').each(function(_, inp) {
inp = $(inp);
var name = inp.attr('name');
idp[name] = inp.val();
thisInvalid = thisInvalid || (name == 'entity_id' && !idp[name].replace(/\s/g, '')) || (name == 'label' && !idp[name].replace(/\s/g, ''));
anyInvalid = anyInvalid || thisInvalid;
if (name == 'logo') {
//idp.logo_data = inp.data('logo_data');
}
});
if (!thisInvalid) {
val.activeIdps.push(idp);
}
});
if (anyInvalid) {
idpWarning.show();
}
else {
idpWarning.hide();
}
// propagate to JSON representation
update();
},
idpWarning = $('<p class="warning">Not all ID providers will be saved! Each entry must have an entity ID and a label.</p>').hide()
;
// link xml input to JSON encoding
$('.shibboleth input[name="xmlPath"]').change(function() {
val.xmlPath = $(this).val();
update();
});

// make idp attribute keys slightly more presentable
var keyToLabel = function(str) {
return str[0].toUpperCase() + str.substr(1).replace('_', ' ') + ': ';
};
var serialized = $('.shibboleth input.serialized');
if (!serialized.length) { console.log('[shib] no serialized input found'); return; }
console.log('[shib] init, serialized name=', serialized.attr('name'));
console.log('[shib] init, serialized initial value=', serialized.val());
var val;
try {
val = JSON.parse(serialized.val());
} catch (e) {
console.error('[shib] failed to parse serialized value:', e, serialized.val());
val = { xmlPath: '', activeIdps: [] };
}
console.log('[shib] init, parsed val=', val);

// try to show a preview of the given logo URL
var updateLogo = function(li) {
return;
var logoInp = li.find('input[name="logo"]'),
href = logoInp ? logoInp.val() : null;
if (!href || !href.replace(/s+/g, '')) {
return;
}
var imgData;
li.find('.preview').remove();
if (href != logoInp.data('orig') || !(imgData = logoInp.data('logo_data'))) {
$.ajax({
'url': '/core/plugins/authentication/shibboleth/fields/institutions.php',
'data': {'img': href},
'success': function(res) {
li.append($('<img class="preview">').attr('src', res));
logoInp.data('logo_data', res);
updateIdps();
},
'error': updateIdps
})
}
else {
li.append($('<img class="preview">').attr('src', imgData));
updateIdps();
}
};
// xmlPath field change
$('#shib-xmlpath').on('change', function() {
val.xmlPath = this.value;
serialized.val(JSON.stringify(val));
console.log('[shib] xmlPath changed; serialized now=', serialized.val());
});

// make a new entry in the idp list
var newActiveIdp = function(idp, before) {
var li = $('<li>')
.append($('<span class="ui-icon ui-icon-arrowthick-2-n-s">'))
.append($('<span class="remove icon">').click(function() {
li.remove();
updateIdps();
}))
[before === true ? 'prependTo' : 'appendTo'](existing);
if (before) {
li.animate('pulsate', 'slow');
}
for (var k in idp) {
if (k === 'logo_data' || k === 'logoData') {
continue;
}
var control = mkInp(k, idp[k]);
if (k == 'logo') {
// control.input.change(function() {
// updateLogo(li);
// });
}
else {
control.input.change(updateIdps);
}
li.append(control.label);
}
// if (idp.logo_data) {
// li.find('input[name="logo"]').data('logo_data', idp.logo_data);
// }
updateLogo(li);
};
// Rebuild activeIdps from currently-checked boxes and sync to hidden input
function updateActiveIdps(reason) {
val.activeIdps = [];
$('.shib-idp-checkbox:checked').each(function() {
var entityId = $(this).val();
var label = $(this).data('label');
var m = entityId.match(/([^.\/:]+\.[^.\/:]+?)(?:\/|$)/);
val.activeIdps.push({
entity_id: entityId,
label: label,
host: m ? m[1] : ''
});
});
serialized.val(JSON.stringify(val));
console.log('[shib] updateActiveIdps (' + reason + '): ' + val.activeIdps.length + ' active; hidden input value length=' + serialized.val().length);
console.log('[shib] hidden input current value=', serialized.val());
}

var normalizeUniversity = function(x) {
if (!x) {
return '';
// Pre-check boxes for already-active IDPs
var activeIds = {};
(val.activeIdps || []).forEach(function(idp) {
activeIds[idp.entity_id] = true;
});
var preChecked = 0;
$('.shib-idp-checkbox').each(function() {
if (activeIds[$(this).val()]) {
$(this).prop('checked', true);
preChecked++;
}
return x.toLowerCase().replace(/^((the|of|university|college)\W)+/, '');
};
});
console.log('[shib] pre-checked ' + preChecked + ' of ' + Object.keys(activeIds).length + ' saved active IDPs');

var addedEntities = {};
if (val.activeIdps) {
val.activeIdps.forEach(function(idp) {
addedEntities[idp.entity_id] = 1;
});
}
// list entities read from the shibboleth conf, if any
if (val.xmlRead) {
var ul = $('<ul class="metadata">');
var addAll = $('<button>Add all</button>').click(function(evt) {
evt.stopPropagation();
ul.find('.add.icon').click();
setTimeout(function() {
console.log(serialized.val());
}, 5000);
return false;
});
prnt.append($('<h4>ID providers in metadata</h4>').append(addAll));
ul.appendTo(prnt);
val.idps.sort(function(a, b) {
a = normalizeUniversity(a.label);
b = normalizeUniversity(b.label);
return a > b ? 1 : -1;
}).forEach(function(idp) {
if (idp.error || addedEntities[idp.entity_id]) {
return;
}
var li = $('<li>');
li.append($('<span class="add icon">').click(function() {
addedEntities[idp.entity_id] = 1;
newActiveIdp(idp, true);
updateIdps();
$(this).parent().remove();
}));
for (var k in idp) {
if (k == 'logo') {
continue;
}
li.append($('<p>').append($('<label>').append($('<span>').text(keyToLabel(k))).append(document.createTextNode(idp[k]))))
}
ul.append(li);
updateLogo(li);
});
}
else {
$('.shibboleth input[name="xmlPath"]').parent().append($('<p class="warning">').text(val.idps));
}
$(document).on('change', '.shib-idp-checkbox', function() {
console.log('[shib] checkbox change: ' + $(this).val() + ' -> ' + this.checked);
updateActiveIdps('change');
});

prnt.append($('<hr>'));
var mkInp = function(lbl, val) {
var inp = $('<input>').val(val).attr('name', lbl).data('orig', val);
return {
'label': $('<p>').append($('<label>').append($('<span>').text(keyToLabel(lbl))).append(inp)),
'input': inp
};
};
$('#item-form').on('submit', function() {
console.log('[shib] item-form submit handler firing');
updateActiveIdps('submit');
});

// new idp entry form
var addNew = $('<div class="new idp">');
['entity_id', 'label', 'host', 'logo'].forEach(function(key) {
var inp = mkInp(key);
addNew.append(inp.label);
// Backstop: also intercept the toolbar Save button click directly,
// since Hubzero.submitform may bypass jQuery submit handlers.
$(document).on('click', 'button.toolbar-submit, a.toolbar-submit, .toolbar button, .toolbar a', function() {
console.log('[shib] toolbar click detected on:', this);
updateActiveIdps('toolbar-click');
});
addNew.append($('<button><span class="add icon"></span> Add ID provider</button>').click(function(evt) {
evt.stopPropagation();
var idp = {};
addNew.find('input').each(function(_, inp) {
inp = $(inp);
idp[inp.attr('name')] = inp.val().replace(/^\s+|\s+$/g, '');
inp.val('');
});
newActiveIdp(idp, true);
updateIdps();
return false;
}));

// append existing active providers
prnt
.append($('<h4>Active ID providers</h4>'))
.append(idpWarning)
.append(addNew);
var existing = $('<ul class="active">').sortable({'stop': updateIdps}).appendTo(prnt);
val.activeIdps.forEach(newActiveIdp);
$('<button>Sort</button>').appendTo(prnt).click(function(evt) {
evt.stopPropagation();
existing.children('li').sort(function(a, b) {
var lblA = $(a).find('input[name=label]').val();
var lblB = $(b).find('input[name=label]').val();
return normalizeUniversity(lblA) > normalizeUniversity(lblB) ? 1 : -1;
}).appendTo(existing);
return false;
// Search / filter checkboxes by display name
$('#shib-idp-search').on('input', function() {
var q = this.value.toLowerCase();
$('.idp-list label').each(function() {
$(this).toggle(!q || $(this).text().toLowerCase().indexOf(q) !== -1);
});
});
});
Loading