ci
build-push / build-push (push) Failing after 24s

This commit is contained in:
chenxing
2026-08-31 18:26:28 +08:00
parent 6daf5db8c1
commit 60da1f6edf
883 changed files with 49953 additions and 0 deletions
@@ -0,0 +1,116 @@
var table;
$(document).ready(function () {
$('#fmrel').on('submit', function (e) {
e.preventDefault();
var username = $('#username').val();
var password = $('#password').val();
var service = $('#service').val();
releaseAttributes(username, password, service);
});
$('#fm1').on('submit', function (e) {
e.preventDefault();
var uid = $('#uid').val();
table = $('#attributesTable').DataTable();
table.clear().draw();
var status = $('#status');
if (uid !== null && uid !== '') {
resolveAttributes(uid);
status.html('Resolved attributes for username <strong>' + uid + '</strong>.');
status.removeClass('alert-danger');
status.addClass('alert-info');
status.show();
} else {
status.html('No username is provided.');
status.removeClass('alert-info');
status.addClass('alert-danger');
status.show();
}
});
if ($.fn.dataTable.isDataTable('#attributesTable')) {
table = $('#attributesTable').DataTable();
} else {
table = $('#attributesTable').DataTable({
paging: false,
searching: false
});
}
$('#status').hide();
});
function resolveAttributes(uid) {
$.ajax({
type: 'post',
url: urls.resolveAttributes,
data: {'uid': uid},
success: function (data) {
var table = $('#attributesTable').DataTable();
table.clear();
var attrs = data.attributes;
for (var property in attrs) {
if (attrs.hasOwnProperty(property)) {
table.row.add([
'<code>' + property + '</code>', '<code>' + attrs[property] + '</code>'
]).draw(false);
}
}
}
});
}
function releaseAttributes(uid, psw, service) {
$('validationresponse').empty();
$('cas1').empty();
$('cas2').empty();
$('cas3Xml').empty();
$('cas3Json').empty();
$('#submitRelease').attr('disabled', 'disabled');
$.ajax({
type: 'post',
url: urls.releaseAttributes,
data: {'username': uid, 'password': psw, 'service': service},
success: function (data) {
var html = '<ul><li>Service Id: <code>' + data.registeredService.id + '</code></li>'
+ '<li>Service Identifier: <code>' + data.registeredService.serviceId + '</code></li>'
+ '<li>Service Name: <code>' + data.registeredService.name + '</code></li>'
+ '</ul><p/>';
$('#validationresponse').html(html);
var resp = '<pre>' + JSON.stringify(data.registeredService, null, 4) + '</pre>';
$('#serviceJson').html(resp);
resp = '<pre>' + data.cas1Response + '</pre>';
$('#cas1').html(resp);
resp = '<pre>' + data.cas2Response + '</pre>';
$('#cas2').html(resp);
resp = '<pre>' + data.cas3XmlResponse + '</pre>';
$('#cas3Xml').html(resp);
resp = '<pre>' + data.cas3JsonResponse + '</pre>';
$('#cas3Json').html(resp);
},
error: function (err) {
var html = '<div class=\'alert alert-danger\'>'
+ '<h4>Response Error</h4>'
+ 'Status: <code>' + err.responseJSON.status + '</code><p/>'
+ 'Exception: <code>' + err.responseJSON.exception + '</code><p/>'
+ 'Message: <code>' + err.responseJSON.message + '</code><p/>'
+ '</div>';
$('#validationresponse').html(html);
},
complete: function() {
$('#submitRelease').removeAttr('disabled');
}
});
}
@@ -0,0 +1,49 @@
$('#myTabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
});
(function () {
var getData = function () {
$.getJSON(urls.getEvents, function (data) {
authnEventsTable(data);
});
};
var authnEventsTable = function (jsonData) {
var t = $('#authnEventsTable').DataTable({
'order': [[2, 'desc']],
retrieve: true,
columnDefs: [
{
'targets': 0,
render: function (data) {
return '<span class="glyphicon glyphicon-flash" aria-hidden="true">&nbsp;</span>' + data;
}
}
]
});
for (var i = 0; i < jsonData.length; i++) {
var rec = jsonData[i];
var type = rec.type.split('.');
t.row.add([
type[type.length - 1],
rec.principalId,
new Date(rec.creationTime*1000),
new Date(rec.timestamp),
rec.properties.agent,
rec.clientIpAddress,
rec.serverIpAddress,
rec.properties.geoLatitude === 'undefined' ? '' : Number(rec.properties.geoLatitude).toFixed(2),
rec.properties.geoLongitude === 'undefined' ? '' : Number(rec.properties.geoLongitude).toFixed(2),
rec.properties.geoAccuracy === 'undefined' ? '' : Number(rec.properties.geoAccuracy).toFixed(2)
]).draw(false);
}
};
// initialization *******
(function init () {
getData();
})();
})();
@@ -0,0 +1,145 @@
/* global trackGeoLocation, jqueryReady */
/* exported resourceLoadedSuccessfully */
function requestGeoPosition() {
// console.log('Requesting GeoLocation data from the browser...');
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showGeoPosition, logGeoLocationError,
{maximumAge: 600000, timeout: 5000, enableHighAccuracy: true});
} else {
// console.log('Browser does not support Geo Location');
}
}
function logGeoLocationError(error) {
switch (error.code) {
case error.PERMISSION_DENIED:
// console.log('User denied the request for GeoLocation.');
break;
case error.POSITION_UNAVAILABLE:
// console.log('Location information is unavailable.');
break;
case error.TIMEOUT:
// console.log('The request to get user location timed out.');
break;
default:
// console.log('An unknown error occurred.');
break;
}
}
function showGeoPosition(position) {
$('[name="geolocation"]').val(position.coords.latitude + ','
+ position.coords.longitude + ',' + position.coords.accuracy + ',' + position.timestamp);
}
function preserveAnchorTagOnForm() {
$('#fm1').submit(function () {
var location = self.document.location;
var hash = decodeURIComponent(location.hash);
if (hash != undefined && hash != '' && hash.indexOf('#') === -1) {
hash = '#' + hash;
}
var action = $('#fm1').attr('action');
if (action == undefined) {
action = location.href;
} else {
var qidx = location.href.indexOf('?');
if (qidx != -1) {
var queryParams = location.href.substring(qidx);
action += queryParams;
}
}
action += hash;
$('#fm1').attr('action', action);
});
}
function areCookiesEnabled() {
if ($.cookie == undefined) {
return;
}
$.cookie('cookiesEnabled', 'true');
var value = $.cookie('cookiesEnabled');
$.removeCookie('cookiesEnabled');
return value != undefined;
}
function disableEmptyInputFormSubmission() {
var fields = $('#fm1 input[name="username"],[name="password"]');
if (fields.length == 2) {
fields.on('input', function (event) {
var enableSubmission = $('#fm1 input[name="username"]').val().trim() &&
$('#fm1 input[name="password"]').val().trim();
if (enableSubmission) {
$('#fm1 input[name=submit]').removeAttr('disabled');
event.stopPropagation();
} else {
$('#fm1 input[name=submit]').attr('disabled', 'true');
}
});
}
/**
* Handle auto-complete events to the extent possible.
*/
if ($('#fm1 input[name="username"]').length > 0) {
setTimeout(function () {
var uid = $('#username').val();
if (uid != null && uid != '') {
$('#username').change();
$('#username').focus();
$('#fm1 input[name=submit]').removeAttr('disabled');
}
}, 100);
}
}
function resourceLoadedSuccessfully() {
$(document).ready(function () {
if (trackGeoLocation) {
requestGeoPosition();
}
if ($(':focus').length === 0) {
$('input:visible:enabled:first').focus();
}
if (areCookiesEnabled()) {
$('#cookiesDisabled').hide();
} else {
$('#cookiesDisabled').show();
}
disableEmptyInputFormSubmission();
preserveAnchorTagOnForm();
$('#capslock-on').hide();
$('#fm1 input[name="username"],[name="password"]').trigger('input');
$('#fm1 input[name="username"]').focus();
$('#password').keypress(function (e) {
var s = String.fromCharCode(e.which);
if (s.toUpperCase() === s && s.toLowerCase() !== s && !e.shiftKey) {
$('#capslock-on').show();
} else {
$('#capslock-on').hide();
}
});
if (typeof(jqueryReady) == 'function') {
jqueryReady();
}
});
}
@@ -0,0 +1,45 @@
var strings = strings;
/* global data */
$(document).ready(function(){
resolveAttributes();
optionSelected();
});
function optionSelected() {
var v = $('input[name=option]:checked', '#fm1').val();
if (v == 0) {
$('#reminderPanel').hide();
$('#reminderTab').hide();
} else {
$('#reminderPanel').show();
$('#reminderTab').show();
}
}
function resolveAttributes() {
var table;
if ( $.fn.dataTable.isDataTable( '#attributesTable' ) ) {
table = $('#attributesTable').DataTable();
}
else {
table = $('#attributesTable').DataTable( {
paging : false,
searching : false,
language: {
info: strings.info
}
} );
}
table.clear();
var attrs = data.attributes;
for (var property in attrs) {
if (attrs.hasOwnProperty(property)) {
table.row.add([
'<code>' + property + '</code>', '<code>' + attrs[property] + '</code>'
]).draw(false);
}
}
}
@@ -0,0 +1,221 @@
var infoEl = $('tr.info').clone();
var strings = strings;
/* Formatting function for row details - modify as you need */
function format(d) {
var detail = infoEl.clone();
// show
$(detail).toggleClass('hidden');
// add data
var dec = d.decision;
// date
detail.find('.created-date')[0].append(date(dec.createdDate).toLocaleString());
// options & reminder
if (dec.options === 'ALWAYS') {
detail.find('.consent-reminder').parent().remove();
} else {
var unit = dec.reminderTimeUnit.toLowerCase();
detail.find('.consent-reminder span:not(.' + unit + ')').remove();
if (dec.reminder === 1) {
var _unit = detail.find('.consent-reminder span.' + unit);
_unit.html(_unit.text().slice(0, -1));
}
detail.find('.consent-reminder').prepend(dec.reminder);
}
detail.find('.consent-options span:not(.' + dec.options.toLowerCase().replace('_','-') + ')').remove();
// render attribute table
attributeTable(detail.find('.consent-attributes'),d.attributes);
// enable tooltip
detail.find('.consent-options [data-toggle="tooltip"]').tooltip();
// setup delete button
var del = detail.find('.btn-danger');
var data = { 'id': dec.id, 'service': dec.service };
del.on('click', data, function (e) {
e.preventDefault();
confirm(e.data.id, e.data.service);
});
return detail;
}
function alertUser(message, alertType) {
$('#alertWrapper').append('<div id="alertdiv" class="alert alert-' + alertType + ' alert-dismissible">' +
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
'<span class="alertMessage">' + message + '</span></div>'
);
setTimeout(function () { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs
$('#alertdiv').remove();
}, 5000);
}
function attributeTable(t, attributes) {
var table;
if ( $.fn.dataTable.isDataTable( t ) ) {
table = $(t).DataTable();
}
else {
table = $(t).DataTable( {
paging : false,
searching : false,
info: false
} );
}
table.clear();
for (var property in attributes) {
if (attributes.hasOwnProperty(property)) {
table.row.add([
'<code>' + property + '</code>', '<code>' + attributes[property] + '</code>'
]).draw(false);
}
}
}
function date(d) {
var date = new Date(d[0],d[1]-1,d[2],d[3],d[4],d[5]);
return date;
}
function confirm(decisionId, service) {
$('#confirmdiv').remove();
var svcStr = service.length > 70 ? service.substr(0,68) + '...' : service;
var message = strings.confirm.replace('{}', svcStr);
$('#alertWrapper').append('<div id="confirmdiv" class="alert alert-warning">' +
'<span class="alertMessage">' + message + '</span><br/>' +
'<button type="button" id="delete" class="btn btn-xs btn-danger" aria-label="Yes"><strong>' +
strings.yes + ' </strong></button>' +
'<button type="button" class="btn btn-xs btn-default" aria-label="No" value="' + decisionId + '"><strong>' +
strings.no + '</strong></button></div>'
);
$('#confirmdiv .btn').click(function() {
$('#confirmdiv').alert('close');
});
$('#delete').click(function() {
removeDecision(decisionId);
});
}
function removeDecision(decisionId) {
var factory = {};
factory.httpHeaders = {};
factory.httpHeaders[$('meta[name=\'_csrf_header\']').attr('content')] = $('meta[name=\'_csrf\']').attr('content');
$.ajax({
type: 'post',
url: urls.delete,
data: {decisionId: decisionId},
headers: factory.httpHeaders,
dataType: 'json',
success: function (data) {
// Reinitialize the table data
$('#consentDecisions').DataTable().ajax.reload();
if (!data) {
alertUser(strings.error, 'danger');
} else {
alertUser(strings.success, 'success');
// Reload the page
location.reload();
}
},
error: function () {
alertUser('There appears to be an error. Please try your request again.', 'danger');
}
});
}
var consentDecisions = (function () {
var createDataTable = function () {
$('#consentDecisions').DataTable({
'order': [[0, 'desc']],
'initComplete': function (settings, json) {
if (!json || json.length == 0) {
$('#consent-decisons').hide();
$('#loadingMessage').hide();
$('#no-consent-decisions').show();
} else {
$('#loadingMessage').hide();
$('#no-consent-decisions').hide();
$('#consent-decisons').show();
}
},
'language': strings.data,
'paging': false,
'ajax': {
'url': urls.getConsentDecisions,
'dataSrc': ''
},
'data': consentDecisions,
'columnDefs': [
{
'targets': 0,
'className': 'created-date',
'data': function (row) {
return date(row.decision.createdDate);
},
'render': function (data) {
var opts = { year: 'numeric', month: 'numeric' };
return '<div class="label label-primary"><span class="hidden">' + data.toISOString() +
'</span>' + data.toLocaleDateString('en', opts ) +
'</div>';
}
},
{
'targets': 1,
'data': 'decision.service',
'className': 'col service-id',
'render': function (data) {
if ($(window).width() <= 855) {
return data.length > 70 ?
'<span title="' + data + '">' + data.substr(0, 68) + '...</span>' : data;
} else {
return data.length > 180 ?
'<span title="' + data + '">' + data.substr(0, 178) + '...</span>' : data;
}
}
}
]
});
};
var addEventHandlers = function () {
/* Performs logout for consent application, no SLO */
$('#logout').click(function() {
var logout = window.location + '/logout';
window.location.assign(logout);
});
// Add event listener for opening and closing details
$(document).on('click', '#consentDecisions > tbody > tr:not(.info)', function () {
var table = $('#consentDecisions').DataTable();
var tr = $(this);
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child(format(row.data()), 'info').show();
tr.addClass('shown');
}
});
};
// initialization *******
(function init() {
createDataTable();
addEventHandlers();
})();
// Public Methods
return {
/**
* Not used
*/
};
})();
@@ -0,0 +1 @@
(function(e,t){if(typeof define==="function"&&define.amd){define([],t)}else if(typeof module==="object"&&module.exports){module.exports=t()}else{var o=t();o._onReady(o.init);e.Duo=o}})(this,function(){var e=/^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/;var t=/^ERR\|[\w\s\.\(\)]+$/;var o=/^DUO_OPEN_WINDOW\|/;var n=["duo.com","duosecurity.com","duomobile.s3-us-west-1.amazonaws.com"];var i="duo_iframe",a="",r="sig_response",s,u,f,d,m,c;function l(e,t){throw new Error("Duo Web SDK error: "+e+(t?"\n"+"See "+t+" for more information":""))}function h(e){return e.replace(/([a-z])([A-Z])/,"$1-$2").toLowerCase()}function p(e,t){if("dataset"in e){return e.dataset[t]}else{return e.getAttribute("data-"+h(t))}}function g(e,t,o,n){if("addEventListener"in window){e.addEventListener(t,n,false)}else{e.attachEvent(o,n)}}function w(e,t,o,n){if("removeEventListener"in window){e.removeEventListener(t,n,false)}else{e.detachEvent(o,n)}}function v(e){g(document,"DOMContentLoaded","onreadystatechange",e)}function _(e){w(document,"DOMContentLoaded","onreadystatechange",e)}function b(e){g(window,"message","onmessage",e)}function E(e){w(window,"message","onmessage",e)}function y(e){if(!e){return}if(e.indexOf("ERR|")===0){l(e.split("|")[1])}if(e.indexOf(":")===-1||e.split(":").length!==2){l("Duo was given a bad token. This might indicate a configuration "+"problem with one of Duo's client libraries.","https://www.duosecurity.com/docs/duoweb#first-steps")}var t=e.split(":");u=e;f=t[0];d=t[1];return{sigRequest:e,duoSig:t[0],appSig:t[1]}}function D(){m=document.getElementById(i);if(!m){throw new Error("This page does not contain an iframe for Duo to use."+'Add an element like <iframe id="duo_iframe"></iframe> '+"to this page. "+"See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe "+"for more information.")}q();_(D)}function O(n){return Boolean(n.origin==="https://"+s&&typeof n.data==="string"&&(n.data.match(e)||n.data.match(t)||n.data.match(o)))}function R(e){if(e){if(e.host){s=e.host}if(e.sig_request){y(e.sig_request)}if(e.post_action){a=e.post_action}if(e.post_argument){r=e.post_argument}if(e.iframe){if(e.iframe.tagName){m=e.iframe}else if(typeof e.iframe==="string"){i=e.iframe}}if(typeof e.submit_callback==="function"){c=e.submit_callback}}if(m){q()}else{m=document.getElementById(i);if(m){q()}else{v(D)}}_(R)}function A(e){if(O(e)){if(e.data.match(o)){var t=e.data.substring("DUO_OPEN_WINDOW|".length);if(L(t)){window.open(t,"_self")}}else{B(e.data);E(A)}}}function L(e){if(!e){return false}var t=document.createElement("a");t.href=e;if(t.protocol==="duotrustedendpoints:"){return true}else if(t.protocol!=="https:"){return false}for(var o=0;o<n.length;o++){if(t.hostname.endsWith("."+n[o])||t.hostname===n[o]){return true}}return false}function q(){if(!s){s=p(m,"host");if(!s){l("No API hostname is given for Duo to use. Be sure to pass "+"a `host` parameter to Duo.init, or through the `data-host` "+"attribute on the iframe element.","https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe")}}if(!f||!d){y(p(m,"sigRequest"));if(!f||!d){l("No valid signed request is given. Be sure to give the "+"`sig_request` parameter to Duo.init, or use the "+"`data-sig-request` attribute on the iframe element.","https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe")}}if(a===""){a=p(m,"postAction")||a}if(r==="sig_response"){r=p(m,"postArgument")||r}m.src=["https://",s,"/frame/web/v1/auth?tx=",f,"&parent=",encodeURIComponent(document.location.href),"&v=2.6"].join("");b(A)}function B(e){var t=document.createElement("input");t.type="hidden";t.name=r;t.value=e+":"+d;var o=document.getElementById("duo_form");if(!o){o=document.createElement("form");m.parentElement.insertBefore(o,m.nextSibling)}o.method="POST";o.action=a;o.appendChild(t);if(typeof c==="function"){c.call(null,o)}else{o.submit()}}return{init:R,_onReady:v,_parseSigRequest:y,_isDuoMessage:O,_doPostBack:B}});
@@ -0,0 +1,342 @@
/* global logConfigFileLocation, SockJS, Stomp */
var stompClient = null;
function setConnected(connected) {
var el = document.getElementById('websocketStatus');
el.style.visibility = connected ? 'visible' : 'hidden';
el.class = connected ? 'alert alert-info' : 'alert alert-danger';
if (!connected) {
el.innerHTML = 'Disconnected!';
} else {
el.innerHTML = 'Connected to CAS. Streaming and tailing logs based on <kbd>[' + logConfigFileLocation + ']</kbd>...';
}
}
function connect() {
$('#logoutputarea').empty();
var socket = new SockJS(urls.reportsWebsocket);
stompClient = Stomp.over(socket);
stompClient.connect({}, function () {
setConnected(true);
stompClient.subscribe('/topic/logs', function (msg) {
if (msg != null && msg.body != '') {
showLogs(msg.body);
}
});
});
}
function disconnect() {
$('#logoutputarea').empty();
$('#logoutputarea').attr('readonly', 'readonly');
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
}
function showLogs(message) {
if (message != '') {
$('#logoutputarea').val($('#logoutputarea').val() + '\n' + message);
$('#logoutputarea').scrollTop(document.getElementById('logoutputarea').scrollHeight);
}
}
disconnect();
connect();
setInterval(function () {
}, 100);
/*************
*
***************/
$('#myTabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
});
var alertHandler = (function () {
var alertContainer = $('#alert-container');
var create = function (message, state) {
//console.log('create the alert');
alertContainer.html('<div class="alert alert-' + state + ' alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button><span>' + message + '</span></div>');
alertContainer.delay(2000).fadeOut('slow');
};
var destroy = function () {
alertContainer.empty();
};
return {
dismiss: function () {
destroy();
},
show: function (msg, state) {
create(msg, state);
}
};
})();
var loggingDashboard = (function () {
var json = null;
var logLevels = ['trace', 'debug', 'info', 'warn', 'error'];
var getData = function () {
$.getJSON(urls.getConfiguration, function (data) {
json = data;
loggerTable();
});
};
var getAuditData = function () {
$.getJSON(urls.getAuditLog, function (data) {
if ($(data).length > 0) {
loggerTableAudit(data);
} else {
$('#auditLogTable').DataTable();
}
});
};
var loggerTableAudit = function (jsonData) {
var t = $('#auditLogTable').DataTable({
'autoWidth': false,
'order': [[3, 'desc']],
retrieve: true,
columnDefs: [
{'width': '5%', 'targets': 0},
{'width': '100%', 'targets': 1},
{
'targets': 2,
render: function (data) {
var dd = data.toLowerCase();
if (dd.indexOf('created') != -1) {
return '<span class="glyphicon glyphicon-plus" aria-hidden="true">&nbsp;</span>' + data;
}
if (dd.indexOf('validated') != -1) {
return '<span class="glyphicon glyphicon-ok" aria-hidden="true">&nbsp;</span>' + data;
}
if (dd.indexOf('destroyed') != -1 || dd.indexOf('deleted') != -1) {
return '<span class="glyphicon glyphicon-minus" aria-hidden="true">&nbsp;</span>' + data;
}
if (dd.indexOf('success') != -1) {
return '<span class="glyphicon glyphicon-thumbs-up" aria-hidden="true">&nbsp;</span>' + data;
}
if (dd.indexOf('failed') != -1) {
return '<span class="glyphicon glyphicon-thumbs-down" aria-hidden="true">&nbsp;</span>' + data;
}
return data;
}
}
]
});
for (var i = 0; i < jsonData.length; i++) {
var rec = jsonData[i];
t.row.add([
rec.principal,
rec.resourceOperatedUpon,
rec.actionPerformed,
new Date(rec.whenActionWasPerformed),
rec.clientIpAddress,
rec.serverIpAddress
]).draw(false);
}
};
var loggerTable = function () {
$('#loggersTable').DataTable({
'autoWidth': false,
'order': [[1, 'desc']],
data: json.loggers,
'drawCallback': function () {
var api = this.api();
if (api.page.info().pages > 1) {
$('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'block';
} else {
$('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'none';
}
},
'initComplete': function (settings) {
if (!settings.aoData || settings.aoData.length == 0) {
$('#loadingMessage').addClass('d-none');
$('#errorLoadingData').removeClass('d-none');
} else {
$('#loadingMessage').addClass('d-none');
$('#errorLoadingData').addClass('d-none');
$('#loggingDashboard .tabsContainer').removeClass('d-none');
}
},
'processing': true,
columnDefs: [
{
'targets': 0,
'className': 'details-control',
'orderable': false,
'data': 'appenders',
'defaultContent': '',
render: function (data) {
if (data.length > 0) {
return '<span></span>';
} else {
return '';
}
}
},
{
targets: 1,
data: 'name',
className: 'col-xs-5'
},
{
targets: 2,
data: 'additive',
className: 'additive col-xs-2',
render: function (data) {
if (data) {
return '<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>';
} else {
return '<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>';
}
}
},
{
targets: 3,
data: 'state',
className: 'col-xs-2'
},
{
targets: 4,
data: 'level',
className: 'col-xs-3',
render: function (data, type, full, meta) {
return toggleSwitch(data, type, full, meta);
}
}
]
});
};
var toggleSwitch = function (data, type, full) {
// Todo: Add additional colors for the other options
//console.log('toggleSwitch data',data);
//console.log('type',type);
//console.log('full',full);
//console.log('meta',meta);
//console.log(logLevels);
var btnColor;
switch (data.toLowerCase()) {
case 'error':
btnColor = 'danger';
break;
case 'info':
btnColor = 'info';
break;
case 'warn':
btnColor = 'warning';
break;
default:
btnColor = 'default';
}
var btnGroup = '<div class="dropdown" data-logger="' + full + '"><button class="btn btn-sm btn-block bg-' + btnColor + ' dropdown-toggle" name="recordinput" data-toggle="dropdown">' + data + ' <span class="caret"></span></button>' +
'<div class="dropdown-menu">';
for (var i = 0; i < logLevels.length; i++) {
btnGroup += '<a class="dropdown-item" href="#">' + logLevels[i].toUpperCase() + '</a>';
}
btnGroup += '</div>';
return btnGroup;
};
/* Formatting function for row details - modify as you need */
var viewAppenders = function (data) {
return '<table class="table table-bordered row-detail"><tbody><tr class="">' +
'<td class="field-label active">Appenders:</td>' +
'<td><kbd>' + JSON.stringify(data.appenders, null, 2) + '</kbd></td>' +
'</tr>' +
'</tbody></table>';
};
var addEventHandlers = function () {
//console.log('addEventHAndlers()');
$(document).on('click', '#loggersTable .dropdown-menu a', function (e) {
//console.log('status change', this);
e.preventDefault();
var selText = $(this).text();
changeLogLevel(selText, this);
});
$(document).on('click', '#loggersTable tbody td.details-control span', function () {
var table = $('#loggersTable').DataTable();
var tr = $(this).closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
} else {
// Open this row
row.child(viewAppenders(row.data()), 'info').show();
tr.addClass('shown');
}
});
};
var changeLogLevel = function (newLevel, el) {
/**
* POST - /cas/status/logging/updateLoggerLevel
* Allows you to change the log level for given LOGGER. Parameters are:
* loggerName, loggerLevel, additive (true/false)
*/
var table = $('#loggersTable').DataTable();
var data = table.row($(el).closest('tr')[0]).data();
if (newLevel != data.level) {
var cell = table.cell($(el).closest('td')[0]);
$.post(urls.updateLevel, {
loggerName: data.name,
loggerLevel: newLevel,
additive: data.additive
}, function () {
cell.data(newLevel).draw();
alertHandler.show('Successfully changed.', 'success');
}).fail(function () {
alertHandler.show('Error saving change. Please try again', 'danger');
});
}
};
// initialization *******
(function init() {
})();
return {
init: function () {
getData();
addEventHandlers();
getAuditData();
},
getJson: function () {
return json;
},
showLoggersTable: function () {
loggerTable();
}
};
})();
loggingDashboard.init();
@@ -0,0 +1,142 @@
/* global jqueryReady, policyPattern, zxcvbn, passwordStrengthI18n */
/*eslint-disable no-unused-vars*/
function jqueryReady() {
var strength = passwordStrengthI18n;
$.fn.zxcvbnProgressBar = function (options) {
//init settings
var settings = $.extend({
allProgressBarClasses: 'progress-bar-danger progress-bar-warning progress-bar-success progress-bar-striped active',
progressBarClass0: 'progress-bar-danger progress-bar-striped active',
progressBarClass1: 'progress-bar-danger progress-bar-striped active',
progressBarClass2: 'progress-bar-warning progress-bar-striped active',
progressBarClass3: 'progress-bar-success',
progressBarClass4: 'progress-bar-success'
}, options);
return this.each(function () {
settings.progressBar = this;
//init progress bar display
UpdateProgressBar();
//Update progress bar on each keypress of password input
$(settings.passwordInput).keyup(function (event) {
UpdateProgressBar();
});
});
function UpdateProgressBar() {
var progressBar = settings.progressBar;
var password = $('#password').val();
if (password) {
var result = zxcvbn(password, settings.userInputs);
//result.score: 0, 1, 2, 3 or 4 - if crack time is less than 10**2, 10**4, 10**6, 10**8, Infinity.
var scorePercentage = (result.score + 1) * 20;
$(progressBar).css('width', scorePercentage + '%');
if (result.score == 0) {
//weak
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass0);
$(progressBar).html(strength[0]);
}
else if (result.score == 1) {
//normal
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass1);
$(progressBar).html(strength[1]);
}
else if (result.score == 2) {
//medium
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass2);
$(progressBar).html(strength[2]);
}
else if (result.score == 3) {
//strong
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass3);
$(progressBar).html(strength[3]);
}
else if (result.score == 4) {
//very strong
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass4);
$(progressBar).html(strength[4]);
}
}
else {
$(progressBar).css('width', '0%');
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass0);
$(progressBar).html('');
}
}
};
var policyPatternRegex = new RegExp(policyPattern);
var password = document.getElementById('password');
var confirmed = document.getElementById('confirmedPassword');
password.addEventListener('input', validate);
confirmed.addEventListener('input', validate);
var alertSettings = {
allAlertClasses: 'fa-times-circle fa-exclamation-circle fa-info-circle fa-check-circle',
alertClassDanger: 'fa-times-circle',
alertClassWarning: 'fa-exclamation-circle',
alertClassInfo: 'fa-info-circle',
alertClassSuccess: 'fa-check-circle'
};
function validate() {
var val = password.value;
var cnf = confirmed.value;
$('#password-policy-violation-msg').hide();
$('#password-confirm-mismatch-msg').hide();
var passwordPolicyViolated = val === '' || !policyPatternRegex.test(val);
var passwordMismatch = val !== '' && val !== cnf;
var disableSubmit = passwordPolicyViolated || passwordMismatch;
$('#submit').prop('disabled', disableSubmit);
var result = zxcvbn(val);
$('#strengthProgressBar').zxcvbnProgressBar({ passwordInput: '#password' });
// Check strength, update the text indicator
if (val !== '') {
$('#password-strength-warning').text(result.feedback.warning);
$('#password-strength-suggestions').text(result.feedback.suggestions);
var clz = alertSettings.alertClassDanger;
switch (result.score) {
case 0:
case 1:
clz = alertSettings.alertClassDanger;
break;
case 2:
clz = alertSettings.alertClassWarning;
break;
case 3:
clz = alertSettings.alertClassInfo;
break;
case 4:
case 5:
default:
clz = alertSettings.alertClassSuccess;
break;
}
$('#password-strength-icon').removeClass(alertSettings.allAlertClasses).addClass(clz);
} else {
$('#password-strength-icon').removeClass(alertSettings.allAlertClasses);
$('#password-strength-warning').text('');
$('#password-strength-suggestions').text('');
}
// Check for mismatch
if (passwordMismatch && cnf !== '') {
$('#password-confirm-mismatch-msg').show();
}
// Check password policy
if (passwordPolicyViolated) {
$('#password-policy-violation-msg').show();
return;
}
}
}
@@ -0,0 +1,351 @@
/*eslint-disable no-unused-vars*/
String.prototype.padLeft = function (length, character) {
return new Array(length - this.length + 1).join(character || ' ') + this;
};
Date.prototype.toFormattedString = function () {
return [String(this.getMonth() + 1).padLeft(2, '0'),
String(this.getDate()).padLeft(2, '0'),
String(this.getFullYear()).substr(2, 2)].join('/') + ' ' +
[String(this.getHours()).padLeft(2, '0'),
String(this.getMinutes()).padLeft(2, '0')].join(':');
};
function principalAttributes(obj) {
var output = '<table class="table table-condensed principal_attributes"><tbody>';
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (Array.isArray(obj[key])) {
output = output.concat('<tr><td class="field-label active">' + key + '</td><td>' + obj[key].toString() + '</td></tr>');
} else {
output = output.concat('<tr><td class="field-label active">' + key + '</td><td>' + obj[key] + '</td></tr>');
}
}
}
output = output.concat('</tbody></table>');
return output;
}
function authenticatedServices(obj) {
var output = '';
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
output = output.concat('<h5>' + key + '</h5><table class="table table-condensed principal_attributes"><tbody>');
for (var foo in obj[key]) {
if (obj[key].hasOwnProperty(foo)) {
if (Array.isArray(obj[key][foo])) {
output = output.concat('<tr><td class="field-label active">' + foo + ':</td><td>' + obj[key][foo].toString() + '</td></tr>');
} else {
output = output.concat('<tr><td class="field-label active">' + foo + ':</td><td>' + obj[key][foo] + '</td></tr>');
}
}
}
output = output.concat('</tbody></table>');
}
}
return output;
}
/* Formatting function for row details - modify as you need */
function format(d) {
return '<table class="table table-bordered row-detail">' +
'<tbody>' +
'<tr class="hidden-md hidden-lg">' +
'<td class="field-label active">Access Date:</td>' +
'<td>' + d.authentication_date_formatted + '</td>' +
'</tr>' +
'<tr class="hidden-md hidden-lg">' +
'<td class="field-label active">Usage Count:</td>' +
'<td>' + d.number_of_uses + '</td>' +
'</tr>' +
'<tr>' +
'<td class="field-label active">Ticket Granting Ticket:</td>' +
'<td>' + d.ticket_granting_ticket + '</td>' +
'</tr>' +
'<tr>' +
'<td class="field-label active">Principal Attributes:</td>' +
'<td>' +
principalAttributes(d.principal_attributes) +
'</td>' +
'</tr>' +
'<tr>' +
'<td class="field-label active">Authenticated Services:</td>' +
'<td>' +
authenticatedServices(d.authenticated_services) +
'</td>' +
'</tr>' +
'<tr>' +
'<td class="field-label active">Ticket Granting Service:</td>' +
'<td></td>' +
'</tr>' +
'</tbody></table>';
}
function updateAdminPanels(data) {
//$('#totalUsers').text(data.totalPrincipals);
$('#totalUsers').text(data.activeSsoSessions.length);
$('#totalUsageSessions').text(sum(data.activeSsoSessions, 'number_of_uses'));
//$('#totalProxied').text(data.totalTicketGrantingTickets);
$('#totalTGTs').text(data.totalTicketGrantingTickets);
//$('#totalTGTs').text( sum(data.activeSsoSessions, 'is_proxied' ) );
}
function sum(obj, prop) {
var sum = 0;
for (var el in obj) {
if (obj.hasOwnProperty(el)) {
sum += ( typeof obj[el][prop] == 'boolean' ) ? +obj[el][prop] : obj[el][prop];
}
}
return sum;
}
/*
function showError(msg) {
$('#msg').removeClass();
$('#msg').addClass('errors');
$('#msg').text(msg);
$('#msg').show();
}
*/
/*
function showInfo(msg) {
$('#msg').removeClass();
$('#msg').addClass('info');
$('#msg').text(msg);
$('#msg').show();
}
*/
function alertUser(message, alertType) {
$('#alertWrapper').append('<div id="alertdiv" class="alert alert-' + alertType + ' alert-dismissible">' +
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
'<span class="alertMessage">' + message + '</span></div>'
);
setTimeout(function () { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs
$('#alertdiv').remove();
}, 5000);
}
function removeSession(ticketId) {
var factory = {};
factory.httpHeaders = {};
factory.messages = {};
factory.httpHeaders[$('meta[name=\'_csrf_header\']').attr('content')] = $('meta[name=\'_csrf\']').attr('content');
factory.ticketId = ticketId;
if (ticketId && (ticketId == 'ALL' || ticketId == 'PROXIED' || ticketId == 'DIRECT' )) {
factory.url = urls.destroy.all;
factory.data = {type: ticketId};
factory.messages.success = 'Removed <strong>' + ticketId + '</strong> tickets successfully.';
factory.messages.error = 'Could not remove <strong>' + ticketId + '</strong> tickets.';
} else {
factory.url = urls.destroy.single;
factory.data = {ticketGrantingTicket: factory.ticketId};
factory.messages.success = 'Ticket is removed successfully.';
factory.messages.error = 'Ticket is not removed successfully.';
}
$.ajax({
type: 'post',
url: factory.url,
//data: { ticketGrantingTicket: factory.ticketId, type: 'ALL' },
data: factory.data,
headers: factory.httpHeaders,
dataType: 'json',
success: function (data) {
// Reinitialize the table data
$('#ssoSessions').DataTable().ajax.reload();
if (data.status != 200) {
alertUser(factory.messages.error, 'danger');
} else {
alertUser(factory.messages.success, 'success');
// Reload the page
location.reload();
}
},
error: function () {
alertUser('There appears to be an error. Please try your request again.', 'danger');
}
});
}
var ssoSessions = (function () {
var createDataTable = function () {
$('#ssoSessions').DataTable({
'order': [[3, 'desc']],
'initComplete': function (settings, json) {
if (!json || json.activeSsoSessions.length == 0) {
$('#loadingMessage').hide();
$('#no-cas-sessions').show();
} else {
updateAdminPanels(json);
$('#loadingMessage').hide();
$('#no-cas-sessions').hide();
$('#cas-sessions').show();
}
},
'language': {
//"infoEmpty": "No active sessions were found",
'emptyTable': 'No sessions found',
'zeroRecords': 'No matching sessions found'
},
'processing': true,
'ajax': {
'url': urls.getSessions,
'dataSrc': 'activeSsoSessions'
},
columnDefs: [
{
'targets': 0,
'className': 'details-control',
'orderable': false,
'data': null,
'defaultContent': ''
},
{
'targets': 1,
'data': 'is_proxied',
'className': 'col-xs-2 col-md-1',
'render': function (data) {
if (data === true) {
return '<span class="label label-primary">Proxy</span>';
} else {
return ' ';
}
}
},
{
'targets': 2,
'data': 'authenticated_principal',
'className': 'col-xs-4 col-md-2',
'render': function (data, type) {
return type === 'display' && data.length > 20 ?
'<span title="' + data + '">' + data.substr(0, 18) + '...</span>' :
data;
}
},
{
'targets': 3,
'data': 'ticket_granting_ticket',
'className': 'hidden-xs hidden-sm col-md-4',
'render': function (data, type) {
return type === 'display' && data.length > 20 ?
'<span title="' + data + '">' + data.substr(0, 40) + '...</span>' :
data;
}
},
{
'targets': 4,
'data': 'authentication_date_formatted',
'className': 'col-xs-4 col-sm-4 col-md-2'
},
{
'targets': 5,
'data': 'number_of_uses',
'className': 'hidden-xs hidden-sm visible-md-* col-md-2'
},
{
'targets': 6,
'data': 'ticket_granting_ticket',
'className': 'col-xs-2 col-sm-2 col-md-1',
'render': function (data) {
return '<button class="btn btn-xs btn-block btn-danger" type="button" value="' + data + '">Destroy</button>';
},
'orderable': false
},
]
});
};
var addEventHandlers = function () {
/**
* The Bulk remove button
*/
$('#removeAllSessionsButton').on('click', function (e) {
e.preventDefault();
removeSession(this.value);
});
/**
* Individual removal button
*/
$(document).on('click', '#ssoSessions tbody tr td:last-child button.btn-danger', function (e) {
e.preventDefault();
removeSession(this.value);
});
/**
* The filter buttons
*/
$('#filterButtons .btn').click(function () {
var filter = $(this).data('filter');
var table = $('#ssoSessions').DataTable();
var filterRegex;
var deleteValue;
var btnText;
// Create Filter RegEx:
if (filter == 'proxied') {
filterRegex = '^Proxy$';
deleteValue = 'PROXIED';
btnText = 'Remove <span class="badge">xx</span> Proxied Sessions';
} else if (filter == 'non-proxied') {
filterRegex = '^ $';
deleteValue = 'DIRECT';
btnText = 'Remove <span class="badge">xx</span> Non-Proxied Sessions';
} else {
filterRegex = '';
deleteValue = 'ALL';
btnText = 'Remove All Sessions';
}
var searchTerm = table.column(1).search(filterRegex, true, false).draw();
$('#removeAllSessionsButton').val(deleteValue).html(btnText.replace('xx', searchTerm.page.info().recordsDisplay));
});
// Add event listener for opening and closing details
$(document).on('click', '#ssoSessions tbody td.details-control', function () {
var table = $('#ssoSessions').DataTable();
var tr = $(this).closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child(format(row.data()), 'info').show();
tr.addClass('shown');
}
});
};
// initialization *******
(function init() {
addEventHandlers();
createDataTable();
})();
// Public Methods
return {
/**
* Not used
*/
};
})();
@@ -0,0 +1,208 @@
/* global d3 */
/*eslint-disable no-unused-vars*/
var Gauge = function (wrapper, percent, options) {
if (!wrapper || !percent) {
//console.error('wrapper and percentage are required. Please check your code.');
return;
}
var label = (!options.label) ? '' : options.label;
var textClass = options.textClass || 'progress-meter';
var width = options.width || 200,
height = options.height || 200,
twoPi = 2 * Math.PI,
progress = 0,
total = 100,
formatPercent = d3.format('.0%');
var colorScale = d3.scaleLinear()
.domain([0, 0.40, 0.50, 1])
.range(['green', 'green', 'goldenrod', 'red']);
var arc = d3.arc()
.startAngle(0)
.innerRadius(width * 0.4)
.outerRadius(width * 0.5)
;
var svg = d3.select(wrapper).append('svg')
.attr('width', width)
.attr('height', height)
.attr('fill', '#2E7AF9')
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
var meter = svg.append('g')
.attr('class', textClass);
meter.append('path')
.attr('class', 'background')
.attr('d', arc.endAngle(twoPi));
var foreground = meter.append('path')
.attr('class', 'foreground');
var text = meter.append('text')
.attr('text-anchor', 'middle');
var text2 = meter.append('text')
.attr('y', height * 0.15)
.attr('text-anchor', 'middle')
.attr('class', 'text2');
text2.text(label);
var animate = function (percentage) {
var i = d3.interpolate(progress, percentage);
foreground.transition().duration(2000)
.tween('progress', function () {
return function (t) {
progress = i(t);
foreground.style('fill', colorScale(progress));
foreground.attr('d', arc.endAngle(twoPi * progress));
text.text(formatPercent(progress));
};
});
};
// init
(function () {
setTimeout(function () {
animate(percent);
}, 500);
})();
return {
update: function (newPercent) {
animate(newPercent);
}
};
};
function upTime(countTo, el) {
var wrapper = document.getElementById('card-uptime');
var element = document.getElementById(el);
var difference = new Date(countTo*1000);
var days = Math.floor(difference / (60 * 60 * 1000 * 24) * 1);
var hours = Math.floor((difference % (60 * 60 * 1000 * 24)) / (60 * 60 * 1000) * 1);
var mins = Math.floor(((difference % (60 * 60 * 1000 * 24)) % (60 * 60 * 1000)) / (60 * 1000) * 1);
var secs = Math.floor((((difference % (60 * 60 * 1000 * 24)) % (60 * 60 * 1000)) % (60 * 1000)) / 1000 * 1);
clearTimeout(upTime.to);
if (isNaN(days) || isNaN(hours) || isNaN(mins) || isNaN(secs) ) {
wrapper.style.display = 'none';
} else {
days = (days == 1) ? days + ' day ' : days + ' days ';
hours = (hours == 1) ? hours + ' hour ' : hours + ' hours ';
mins = (mins == 1) ? mins + ' minute ' : mins + ' minutes ';
secs = (secs == 1) ? secs + ' second ' : secs + ' seconds';
var timeString = '<span class="upTime">' + days + hours + mins + secs + '</span>';
element.innerHTML = timeString;
wrapper.style.display = 'block';
upTime.to = setTimeout(function() {
countTo = countTo + 1;
upTime(countTo, el);
},1000);
}
}
var analytics = document.getElementById('expiredSts');
var casStatistics = function (urls, messages) {
var timers = {
memory: 5000,
availability: 15000,
tickets: 5000
};
var memoryGauage;
var getRemoteJSON = function(url) {
return $.getJSON( url);
};
var tickets = function() {
var data = getRemoteJSON(urls.tickets);
data.done(function( data ) {
updateElementValue( 'unexpiredTgts', data.unexpiredTgts );
updateElementValue( 'unexpiredSts', data.unexpiredSts );
updateElementValue( 'expiredTgts', data.expiredTgts );
updateElementValue( 'expiredSts', data.expiredSts );
setTimeout( tickets, timers.tickets );
});
};
var updateElementValue = function(el, val) {
$( '#' + el ).text( val );
};
var memory = function() {
var data = getRemoteJSON(urls.memory);
data.done(function( data ) {
updateElementValue('freeMemory', data.freeMemory.toFixed(2));
// updateElementValue('totalMemory', data.totalMemory);
// updateElementValue('maxMemory', data.maxMemory);
// updateElementValue('availableProcessors', data.availableProcessors);
var memCalc = (data.totalMemory / data.maxMemory).toFixed(2);
if ( !memoryGauage ) {
memoryGauage = new Gauge('#maxMemoryGauge', memCalc, {width: 200, height: 200,
label: messages.memoryGaugeTitle,
textClass: 'runtimeStatistics'});
} else {
memoryGauage.update( memCalc );
}
setTimeout( memory, timers.memory );
});
};
var availability = function() {
var data = getRemoteJSON(urls.availability);
data.done(function( data ) {
updateElementValue('upTime', data.upTime);
setTimeout( availability, timers.availability );
});
};
// initialization *******
( function init () {
$('#loading, .statisticsView').toggle();
tickets();
memory();
// availability();
})();
// Public Methods
return {
getTickets: function() {
return tickets();
},
getMemory: function() {
return memory();
},
getAvailability: function() {
return availability();
},
updateGauge: function(val){
if (memoryGauage) {
memoryGauage.update( val );
} else {
return 'unable to update';
}
}
};
};
@@ -0,0 +1,474 @@
// Generated by CoffeeScript 1.7.1
/*
Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0
Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/)
Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com)
*/
(function() {
var Byte, Client, Frame, Stomp,
__hasProp = {}.hasOwnProperty,
__slice = [].slice;
Byte = {
LF: '\x0A',
NULL: '\x00'
};
Frame = (function() {
var unmarshallSingle;
function Frame(command, headers, body) {
this.command = command;
this.headers = headers != null ? headers : {};
this.body = body != null ? body : '';
}
Frame.prototype.toString = function() {
var lines, name, value, _ref;
lines = [this.command];
_ref = this.headers;
for (name in _ref) {
if (!__hasProp.call(_ref, name)) continue;
value = _ref[name];
lines.push("" + name + ":" + value);
}
if (this.body) {
lines.push("content-length:" + (Frame.sizeOfUTF8(this.body)));
}
lines.push(Byte.LF + this.body);
return lines.join(Byte.LF);
};
Frame.sizeOfUTF8 = function(s) {
if (s) {
return encodeURI(s).split(/%..|./).length - 1;
} else {
return 0;
}
};
unmarshallSingle = function(data) {
var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref, _ref1;
divider = data.search(RegExp("" + Byte.LF + Byte.LF));
headerLines = data.substring(0, divider).split(Byte.LF);
command = headerLines.shift();
headers = {};
trim = function(str) {
return str.replace(/^\s+|\s+$/g, '');
};
_ref = headerLines.reverse();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
line = _ref[_i];
idx = line.indexOf(':');
headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1));
}
body = '';
start = divider + 2;
if (headers['content-length']) {
len = parseInt(headers['content-length']);
body = ('' + data).substring(start, start + len);
} else {
chr = null;
for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) {
chr = data.charAt(i);
if (chr === Byte.NULL) {
break;
}
body += chr;
}
}
return new Frame(command, headers, body);
};
Frame.unmarshall = function(datas) {
var data;
return (function() {
var _i, _len, _ref, _results;
_ref = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*"));
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
data = _ref[_i];
if ((data != null ? data.length : void 0) > 0) {
_results.push(unmarshallSingle(data));
}
}
return _results;
})();
};
Frame.marshall = function(command, headers, body) {
var frame;
frame = new Frame(command, headers, body);
return frame.toString() + Byte.NULL;
};
return Frame;
})();
Client = (function() {
var now;
function Client(ws) {
this.ws = ws;
this.ws.binaryType = "arraybuffer";
this.counter = 0;
this.connected = false;
this.heartbeat = {
outgoing: 10000,
incoming: 10000
};
this.maxWebSocketFrameSize = 16 * 1024;
this.subscriptions = {};
}
Client.prototype.debug = function(message) {
void 0;
};
now = function() {
return Date.now || new Date().valueOf;
};
Client.prototype._transmit = function(command, headers, body) {
var out;
out = Frame.marshall(command, headers, body);
if (typeof this.debug === "function") {
this.debug(">>> " + out);
}
while (true) {
if (out.length > this.maxWebSocketFrameSize) {
this.ws.send(out.substring(0, this.maxWebSocketFrameSize));
out = out.substring(this.maxWebSocketFrameSize);
if (typeof this.debug === "function") {
this.debug("remaining = " + out.length);
}
} else {
return this.ws.send(out);
}
}
};
Client.prototype._setupHeartbeat = function(headers) {
var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1;
if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) {
return;
}
_ref1 = (function() {
var _i, _len, _ref1, _results;
_ref1 = headers['heart-beat'].split(",");
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
v = _ref1[_i];
_results.push(parseInt(v));
}
return _results;
})(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1];
if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) {
ttl = Math.max(this.heartbeat.outgoing, serverIncoming);
if (typeof this.debug === "function") {
this.debug("send PING every " + ttl + "ms");
}
this.pinger = Stomp.setInterval(ttl, (function(_this) {
return function() {
_this.ws.send(Byte.LF);
return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0;
};
})(this));
}
if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) {
ttl = Math.max(this.heartbeat.incoming, serverOutgoing);
if (typeof this.debug === "function") {
this.debug("check PONG every " + ttl + "ms");
}
return this.ponger = Stomp.setInterval(ttl, (function(_this) {
return function() {
var delta;
delta = now() - _this.serverActivity;
if (delta > ttl * 2) {
if (typeof _this.debug === "function") {
_this.debug("did not receive server activity for the last " + delta + "ms");
}
return _this.ws.close();
}
};
})(this));
}
};
Client.prototype._parseConnect = function() {
var args, connectCallback, errorCallback, headers;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
headers = {};
switch (args.length) {
case 2:
headers = args[0], connectCallback = args[1];
break;
case 3:
if (args[1] instanceof Function) {
headers = args[0], connectCallback = args[1], errorCallback = args[2];
} else {
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2];
}
break;
case 4:
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3];
break;
default:
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4];
}
return [headers, connectCallback, errorCallback];
};
Client.prototype.connect = function() {
var args, errorCallback, headers, out;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
out = this._parseConnect.apply(this, args);
headers = out[0], this.connectCallback = out[1], errorCallback = out[2];
if (typeof this.debug === "function") {
this.debug("Opening Web Socket...");
}
this.ws.onmessage = (function(_this) {
return function(evt) {
var arr, c, client, data, frame, messageID, onreceive, subscription, _i, _len, _ref, _results;
data = typeof ArrayBuffer !== 'undefined' && evt.data instanceof ArrayBuffer ? (arr = new Uint8Array(evt.data), typeof _this.debug === "function" ? _this.debug("--- got data length: " + arr.length) : void 0, ((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = arr.length; _i < _len; _i++) {
c = arr[_i];
_results.push(String.fromCharCode(c));
}
return _results;
})()).join('')) : evt.data;
_this.serverActivity = now();
if (data === Byte.LF) {
if (typeof _this.debug === "function") {
_this.debug("<<< PONG");
}
return;
}
if (typeof _this.debug === "function") {
_this.debug("<<< " + data);
}
_ref = Frame.unmarshall(data);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
frame = _ref[_i];
switch (frame.command) {
case "CONNECTED":
if (typeof _this.debug === "function") {
_this.debug("connected to server " + frame.headers.server);
}
_this.connected = true;
_this._setupHeartbeat(frame.headers);
_results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0);
break;
case "MESSAGE":
subscription = frame.headers.subscription;
onreceive = _this.subscriptions[subscription] || _this.onreceive;
if (onreceive) {
client = _this;
messageID = frame.headers["message-id"];
frame.ack = function(headers) {
if (headers == null) {
headers = {};
}
return client.ack(messageID, subscription, headers);
};
frame.nack = function(headers) {
if (headers == null) {
headers = {};
}
return client.nack(messageID, subscription, headers);
};
_results.push(onreceive(frame));
} else {
_results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0);
}
break;
case "RECEIPT":
_results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0);
break;
case "ERROR":
_results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0);
break;
default:
_results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0);
}
}
return _results;
};
})(this);
this.ws.onclose = (function(_this) {
return function() {
var msg;
msg = "Whoops! Lost connection to " + _this.ws.url;
if (typeof _this.debug === "function") {
_this.debug(msg);
}
_this._cleanUp();
return typeof errorCallback === "function" ? errorCallback(msg) : void 0;
};
})(this);
return this.ws.onopen = (function(_this) {
return function() {
if (typeof _this.debug === "function") {
_this.debug('Web Socket Opened...');
}
headers["accept-version"] = Stomp.VERSIONS.supportedVersions();
headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(',');
return _this._transmit("CONNECT", headers);
};
})(this);
};
Client.prototype.disconnect = function(disconnectCallback) {
this._transmit("DISCONNECT");
this.ws.onclose = null;
this.ws.close();
this._cleanUp();
return typeof disconnectCallback === "function" ? disconnectCallback() : void 0;
};
Client.prototype._cleanUp = function() {
this.connected = false;
if (this.pinger) {
Stomp.clearInterval(this.pinger);
}
if (this.ponger) {
return Stomp.clearInterval(this.ponger);
}
};
Client.prototype.send = function(destination, headers, body) {
if (headers == null) {
headers = {};
}
if (body == null) {
body = '';
}
headers.destination = destination;
return this._transmit("SEND", headers, body);
};
Client.prototype.subscribe = function(destination, callback, headers) {
var client;
if (headers == null) {
headers = {};
}
if (!headers.id) {
headers.id = "sub-" + this.counter++;
}
headers.destination = destination;
this.subscriptions[headers.id] = callback;
this._transmit("SUBSCRIBE", headers);
client = this;
return {
id: headers.id,
unsubscribe: function() {
return client.unsubscribe(headers.id);
}
};
};
Client.prototype.unsubscribe = function(id) {
delete this.subscriptions[id];
return this._transmit("UNSUBSCRIBE", {
id: id
});
};
Client.prototype.begin = function(transaction) {
var client, txid;
txid = transaction || "tx-" + this.counter++;
this._transmit("BEGIN", {
transaction: txid
});
client = this;
return {
id: txid,
commit: function() {
return client.commit(txid);
},
abort: function() {
return client.abort(txid);
}
};
};
Client.prototype.commit = function(transaction) {
return this._transmit("COMMIT", {
transaction: transaction
});
};
Client.prototype.abort = function(transaction) {
return this._transmit("ABORT", {
transaction: transaction
});
};
Client.prototype.ack = function(messageID, subscription, headers) {
if (headers == null) {
headers = {};
}
headers["message-id"] = messageID;
headers.subscription = subscription;
return this._transmit("ACK", headers);
};
Client.prototype.nack = function(messageID, subscription, headers) {
if (headers == null) {
headers = {};
}
headers["message-id"] = messageID;
headers.subscription = subscription;
return this._transmit("NACK", headers);
};
return Client;
})();
Stomp = {
VERSIONS: {
V1_0: '1.0',
V1_1: '1.1',
V1_2: '1.2',
supportedVersions: function() {
return '1.1,1.0';
}
},
client: function(url, protocols) {
var klass, ws;
if (protocols == null) {
protocols = ['v10.stomp', 'v11.stomp'];
}
klass = Stomp.WebSocketClass || WebSocket;
ws = new klass(url, protocols);
return new Client(ws);
},
over: function(ws) {
return new Client(ws);
},
Frame: Frame
};
if (typeof window !== "undefined" && window !== null) {
Stomp.setInterval = function(interval, f) {
return window.setInterval(f, interval);
};
Stomp.clearInterval = function(id) {
return window.clearInterval(id);
};
window.Stomp = Stomp;
} else if (typeof exports !== "undefined" && exports !== null) {
exports.Stomp = Stomp;
} else {
self.Stomp = Stomp;
}
}).call(this);
@@ -0,0 +1,59 @@
/*eslint-disable no-unused-vars*/
$('#myTabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
});
var revokeDevice = function (key) {
$.ajax({
type: 'post',
url: urls.revokeRecord,
data: {'key': key},
success: function () {
var table = $('#trustedDevicesTable').DataTable();
table
.rows($('#' + key).parents('tr'))
.remove()
.draw();
},
error: function () {
//console.log('Could not remove record');
}
});
};
var trustedDevices = (function () {
var getData = function () {
$.getJSON(urls.getRecords, function (data) {
trustedDevicesTable(data);
});
};
var trustedDevicesTable = function (jsonData) {
var t = $('#trustedDevicesTable').DataTable({
'order': [[2, 'desc']],
columnDefs: [
{'width': '20%', 'targets': 0},
{'width': '10%', 'targets': 1},
{'width': '60%', 'targets': 2},
{'width': '10%', 'targets': 3},
{'width': '30%', 'targets': 4}
]
});
for (var i = 0; i < jsonData.length; i++) {
var rec = jsonData[i];
t.row.add([
rec.name,
rec.principal,
new Date(rec.date),
rec.geography,
'<button id=\'' + rec.key + '\' class=\'btn btn-sm btn-danger\' type=\'button\' value=\'ALL\' onclick=\'revokeDevice("' + rec.key + '")\'>Revoke</button>'
]).draw(false);
}
};
// initialization *******
(function init() {
getData();
})();
})();
@@ -0,0 +1,748 @@
//Copyright 2014-2015 Google Inc. All rights reserved.
//Use of this source code is governed by a BSD-style
//license that can be found in the LICENSE file or at
//https://developers.google.com/open-source/licenses/bsd
/**
* @fileoverview The U2F api.
*/
'use strict';
/**
* Namespace for the U2F api.
* @type {Object}
*/
var u2f = u2f || {};
/**
* FIDO U2F Javascript API Version
* @number
*/
var js_api_version;
/**
* The U2F extension id
* @const {string}
*/
// The Chrome packaged app extension ID.
// Uncomment this if you want to deploy a server instance that uses
// the package Chrome app and does not require installing the U2F Chrome extension.
u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
// The U2F Chrome extension ID.
// Uncomment this if you want to deploy a server instance that uses
// the U2F Chrome extension to authenticate.
// u2f.EXTENSION_ID = 'pfboblefjcgdjicmnffhdgionmgcdmne';
/**
* Message types for messsages to/from the extension
* @const
* @enum {string}
*/
u2f.MessageTypes = {
'U2F_REGISTER_REQUEST': 'u2f_register_request',
'U2F_REGISTER_RESPONSE': 'u2f_register_response',
'U2F_SIGN_REQUEST': 'u2f_sign_request',
'U2F_SIGN_RESPONSE': 'u2f_sign_response',
'U2F_GET_API_VERSION_REQUEST': 'u2f_get_api_version_request',
'U2F_GET_API_VERSION_RESPONSE': 'u2f_get_api_version_response'
};
/**
* Response status codes
* @const
* @enum {number}
*/
u2f.ErrorCodes = {
'OK': 0,
'OTHER_ERROR': 1,
'BAD_REQUEST': 2,
'CONFIGURATION_UNSUPPORTED': 3,
'DEVICE_INELIGIBLE': 4,
'TIMEOUT': 5
};
/**
* A message for registration requests
* @typedef {{
* type: u2f.MessageTypes,
* appId: ?string,
* timeoutSeconds: ?number,
* requestId: ?number
* }}
*/
u2f.U2fRequest;
/**
* A message for registration responses
* @typedef {{
* type: u2f.MessageTypes,
* responseData: (u2f.Error | u2f.RegisterResponse | u2f.SignResponse),
* requestId: ?number
* }}
*/
u2f.U2fResponse;
/**
* An error object for responses
* @typedef {{
* errorCode: u2f.ErrorCodes,
* errorMessage: ?string
* }}
*/
u2f.Error;
/**
* Data object for a single sign request.
* @typedef {enum {BLUETOOTH_RADIO, BLUETOOTH_LOW_ENERGY, USB, NFC}}
*/
u2f.Transport;
/**
* Data object for a single sign request.
* @typedef {Array<u2f.Transport>}
*/
u2f.Transports;
/**
* Data object for a single sign request.
* @typedef {{
* version: string,
* challenge: string,
* keyHandle: string,
* appId: string
* }}
*/
u2f.SignRequest;
/**
* Data object for a sign response.
* @typedef {{
* keyHandle: string,
* signatureData: string,
* clientData: string
* }}
*/
u2f.SignResponse;
/**
* Data object for a registration request.
* @typedef {{
* version: string,
* challenge: string
* }}
*/
u2f.RegisterRequest;
/**
* Data object for a registration response.
* @typedef {{
* version: string,
* keyHandle: string,
* transports: Transports,
* appId: string
* }}
*/
u2f.RegisterResponse;
/**
* Data object for a registered key.
* @typedef {{
* version: string,
* keyHandle: string,
* transports: ?Transports,
* appId: ?string
* }}
*/
u2f.RegisteredKey;
/**
* Data object for a get API register response.
* @typedef {{
* js_api_version: number
* }}
*/
u2f.GetJsApiVersionResponse;
//Low level MessagePort API support
/**
* Sets up a MessagePort to the U2F extension using the
* available mechanisms.
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
*/
u2f.getMessagePort = function(callback) {
if (typeof chrome != 'undefined' && chrome.runtime) {
// The actual message here does not matter, but we need to get a reply
// for the callback to run. Thus, send an empty signature request
// in order to get a failure response.
var msg = {
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
signRequests: []
};
chrome.runtime.sendMessage(u2f.EXTENSION_ID, msg, function() {
if (!chrome.runtime.lastError) {
// We are on a whitelisted origin and can talk directly
// with the extension.
u2f.getChromeRuntimePort_(callback);
} else {
// chrome.runtime was available, but we couldn't message
// the extension directly, use iframe
u2f.getIframePort_(callback);
}
});
} else if (u2f.isAndroidChrome_()) {
u2f.getAuthenticatorPort_(callback);
} else if (u2f.isIosChrome_()) {
u2f.getIosPort_(callback);
} else {
// chrome.runtime was not available at all, which is normal
// when this origin doesn't have access to any extensions.
u2f.getIframePort_(callback);
}
};
/**
* Detect chrome running on android based on the browser's useragent.
* @private
*/
u2f.isAndroidChrome_ = function() {
var userAgent = navigator.userAgent;
return userAgent.indexOf('Chrome') != -1 &&
userAgent.indexOf('Android') != -1;
};
/**
* Detect chrome running on iOS based on the browser's platform.
* @private
*/
u2f.isIosChrome_ = function() {
return ["iPhone", "iPad", "iPod"].indexOf(navigator.platform) > -1;
};
/**
* Connects directly to the extension via chrome.runtime.connect.
* @param {function(u2f.WrappedChromeRuntimePort_)} callback
* @private
*/
u2f.getChromeRuntimePort_ = function(callback) {
var port = chrome.runtime.connect(u2f.EXTENSION_ID,
{'includeTlsChannelId': true});
setTimeout(function() {
callback(new u2f.WrappedChromeRuntimePort_(port));
}, 0);
};
/**
* Return a 'port' abstraction to the Authenticator app.
* @param {function(u2f.WrappedAuthenticatorPort_)} callback
* @private
*/
u2f.getAuthenticatorPort_ = function(callback) {
setTimeout(function() {
callback(new u2f.WrappedAuthenticatorPort_());
}, 0);
};
/**
* Return a 'port' abstraction to the iOS client app.
* @param {function(u2f.WrappedIosPort_)} callback
* @private
*/
u2f.getIosPort_ = function(callback) {
setTimeout(function() {
callback(new u2f.WrappedIosPort_());
}, 0);
};
/**
* A wrapper for chrome.runtime.Port that is compatible with MessagePort.
* @param {Port} port
* @constructor
* @private
*/
u2f.WrappedChromeRuntimePort_ = function(port) {
this.port_ = port;
};
/**
* Format and return a sign request compliant with the JS API version supported by the extension.
* @param {Array<u2f.SignRequest>} signRequests
* @param {number} timeoutSeconds
* @param {number} reqId
* @return {Object}
*/
u2f.formatSignRequest_ =
function(appId, challenge, registeredKeys, timeoutSeconds, reqId) {
if (js_api_version === undefined || js_api_version < 1.1) {
// Adapt request to the 1.0 JS API
var signRequests = [];
for (var i = 0; i < registeredKeys.length; i++) {
signRequests[i] = {
version: registeredKeys[i].version,
challenge: challenge,
keyHandle: registeredKeys[i].keyHandle,
appId: appId
};
}
return {
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
signRequests: signRequests,
timeoutSeconds: timeoutSeconds,
requestId: reqId
};
}
// JS 1.1 API
return {
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
appId: appId,
challenge: challenge,
registeredKeys: registeredKeys,
timeoutSeconds: timeoutSeconds,
requestId: reqId
};
};
/**
* Format and return a register request compliant with the JS API version supported by the extension..
* @param {Array<u2f.SignRequest>} signRequests
* @param {Array<u2f.RegisterRequest>} signRequests
* @param {number} timeoutSeconds
* @param {number} reqId
* @return {Object}
*/
u2f.formatRegisterRequest_ =
function(appId, registeredKeys, registerRequests, timeoutSeconds, reqId) {
if (js_api_version === undefined || js_api_version < 1.1) {
// Adapt request to the 1.0 JS API
for (var i = 0; i < registerRequests.length; i++) {
registerRequests[i].appId = appId;
}
var signRequests = [];
for (var i = 0; i < registeredKeys.length; i++) {
signRequests[i] = {
version: registeredKeys[i].version,
challenge: registerRequests[0],
keyHandle: registeredKeys[i].keyHandle,
appId: appId
};
}
return {
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
signRequests: signRequests,
registerRequests: registerRequests,
timeoutSeconds: timeoutSeconds,
requestId: reqId
};
}
// JS 1.1 API
return {
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
appId: appId,
registerRequests: registerRequests,
registeredKeys: registeredKeys,
timeoutSeconds: timeoutSeconds,
requestId: reqId
};
};
/**
* Posts a message on the underlying channel.
* @param {Object} message
*/
u2f.WrappedChromeRuntimePort_.prototype.postMessage = function(message) {
this.port_.postMessage(message);
};
/**
* Emulates the HTML 5 addEventListener interface. Works only for the
* onmessage event, which is hooked up to the chrome.runtime.Port.onMessage.
* @param {string} eventName
* @param {function({data: Object})} handler
*/
u2f.WrappedChromeRuntimePort_.prototype.addEventListener =
function(eventName, handler) {
var name = eventName.toLowerCase();
if (name == 'message' || name == 'onmessage') {
this.port_.onMessage.addListener(function(message) {
// Emulate a minimal MessageEvent object
handler({'data': message});
});
} else {
console.error('WrappedChromeRuntimePort only supports onMessage');
}
};
/**
* Wrap the Authenticator app with a MessagePort interface.
* @constructor
* @private
*/
u2f.WrappedAuthenticatorPort_ = function() {
this.requestId_ = -1;
this.requestObject_ = null;
}
/**
* Launch the Authenticator intent.
* @param {Object} message
*/
u2f.WrappedAuthenticatorPort_.prototype.postMessage = function(message) {
var intentUrl =
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
';S.request=' + encodeURIComponent(JSON.stringify(message)) +
';end';
document.location = intentUrl;
};
/**
* Tells what type of port this is.
* @return {String} port type
*/
u2f.WrappedAuthenticatorPort_.prototype.getPortType = function() {
return "WrappedAuthenticatorPort_";
};
/**
* Emulates the HTML 5 addEventListener interface.
* @param {string} eventName
* @param {function({data: Object})} handler
*/
u2f.WrappedAuthenticatorPort_.prototype.addEventListener = function(eventName, handler) {
var name = eventName.toLowerCase();
if (name == 'message') {
var self = this;
/* Register a callback to that executes when
* chrome injects the response. */
window.addEventListener(
'message', self.onRequestUpdate_.bind(self, handler), false);
} else {
console.error('WrappedAuthenticatorPort only supports message');
}
};
/**
* Callback invoked when a response is received from the Authenticator.
* @param function({data: Object}) callback
* @param {Object} message message Object
*/
u2f.WrappedAuthenticatorPort_.prototype.onRequestUpdate_ =
function(callback, message) {
var messageObject = JSON.parse(message.data);
var intentUrl = messageObject['intentURL'];
var errorCode = messageObject['errorCode'];
var responseObject = null;
if (messageObject.hasOwnProperty('data')) {
responseObject = /** @type {Object} */ (
JSON.parse(messageObject['data']));
}
callback({'data': responseObject});
};
/**
* Base URL for intents to Authenticator.
* @const
* @private
*/
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ =
'intent:#Intent;action=com.google.android.apps.authenticator.AUTHENTICATE';
/**
* Wrap the iOS client app with a MessagePort interface.
* @constructor
* @private
*/
u2f.WrappedIosPort_ = function() {};
/**
* Launch the iOS client app request
* @param {Object} message
*/
u2f.WrappedIosPort_.prototype.postMessage = function(message) {
var str = JSON.stringify(message);
var url = "u2f://auth?" + encodeURI(str);
location.replace(url);
};
/**
* Tells what type of port this is.
* @return {String} port type
*/
u2f.WrappedIosPort_.prototype.getPortType = function() {
return "WrappedIosPort_";
};
/**
* Emulates the HTML 5 addEventListener interface.
* @param {string} eventName
* @param {function({data: Object})} handler
*/
u2f.WrappedIosPort_.prototype.addEventListener = function(eventName, handler) {
var name = eventName.toLowerCase();
if (name !== 'message') {
console.error('WrappedIosPort only supports message');
}
};
/**
* Sets up an embedded trampoline iframe, sourced from the extension.
* @param {function(MessagePort)} callback
* @private
*/
u2f.getIframePort_ = function(callback) {
// Create the iframe
var iframeOrigin = 'chrome-extension://' + u2f.EXTENSION_ID;
var iframe = document.createElement('iframe');
iframe.src = iframeOrigin + '/u2f-comms.html';
iframe.setAttribute('style', 'display:none');
document.body.appendChild(iframe);
var channel = new MessageChannel();
var ready = function(message) {
if (message.data == 'ready') {
channel.port1.removeEventListener('message', ready);
callback(channel.port1);
} else {
console.error('First event on iframe port was not "ready"');
}
};
channel.port1.addEventListener('message', ready);
channel.port1.start();
iframe.addEventListener('load', function() {
// Deliver the port to the iframe and initialize
iframe.contentWindow.postMessage('init', iframeOrigin, [channel.port2]);
});
};
//High-level JS API
/**
* Default extension response timeout in seconds.
* @const
*/
u2f.EXTENSION_TIMEOUT_SEC = 30;
/**
* A singleton instance for a MessagePort to the extension.
* @type {MessagePort|u2f.WrappedChromeRuntimePort_}
* @private
*/
u2f.port_ = null;
/**
* Callbacks waiting for a port
* @type {Array<function((MessagePort|u2f.WrappedChromeRuntimePort_))>}
* @private
*/
u2f.waitingForPort_ = [];
/**
* A counter for requestIds.
* @type {number}
* @private
*/
u2f.reqCounter_ = 0;
/**
* A map from requestIds to client callbacks
* @type {Object.<number,(function((u2f.Error|u2f.RegisterResponse))
* |function((u2f.Error|u2f.SignResponse)))>}
* @private
*/
u2f.callbackMap_ = {};
/**
* Creates or retrieves the MessagePort singleton to use.
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
* @private
*/
u2f.getPortSingleton_ = function(callback) {
if (u2f.port_) {
callback(u2f.port_);
} else {
if (u2f.waitingForPort_.length == 0) {
u2f.getMessagePort(function(port) {
u2f.port_ = port;
u2f.port_.addEventListener('message',
/** @type {function(Event)} */ (u2f.responseHandler_));
// Careful, here be async callbacks. Maybe.
while (u2f.waitingForPort_.length)
u2f.waitingForPort_.shift()(u2f.port_);
});
}
u2f.waitingForPort_.push(callback);
}
};
/**
* Handles response messages from the extension.
* @param {MessageEvent.<u2f.Response>} message
* @private
*/
u2f.responseHandler_ = function(message) {
var response = message.data;
var reqId = response['requestId'];
if (!reqId || !u2f.callbackMap_[reqId]) {
console.error('Unknown or missing requestId in response.');
return;
}
var cb = u2f.callbackMap_[reqId];
delete u2f.callbackMap_[reqId];
cb(response['responseData']);
};
/**
* Dispatches an array of sign requests to available U2F tokens.
* If the JS API version supported by the extension is unknown, it first sends a
* message to the extension to find out the supported API version and then it sends
* the sign request.
* @param {string=} appId
* @param {string=} challenge
* @param {Array<u2f.RegisteredKey>} registeredKeys
* @param {function((u2f.Error|u2f.SignResponse))} callback
* @param {number=} opt_timeoutSeconds
*/
u2f.sign = function(appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
if (js_api_version === undefined) {
// Send a message to get the extension to JS API version, then send the actual sign request.
u2f.getApiVersion(
function (response) {
js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
console.log("Extension JS API Version: ", js_api_version);
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
});
} else {
// We know the JS API version. Send the actual sign request in the supported API version.
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
}
};
/**
* Dispatches an array of sign requests to available U2F tokens.
* @param {string=} appId
* @param {string=} challenge
* @param {Array<u2f.RegisteredKey>} registeredKeys
* @param {function((u2f.Error|u2f.SignResponse))} callback
* @param {number=} opt_timeoutSeconds
*/
u2f.sendSignRequest = function(appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
u2f.getPortSingleton_(function(port) {
var reqId = ++u2f.reqCounter_;
u2f.callbackMap_[reqId] = callback;
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
var req = u2f.formatSignRequest_(appId, challenge, registeredKeys, timeoutSeconds, reqId);
port.postMessage(req);
});
};
/**
* Dispatches register requests to available U2F tokens. An array of sign
* requests identifies already registered tokens.
* If the JS API version supported by the extension is unknown, it first sends a
* message to the extension to find out the supported API version and then it sends
* the register request.
* @param {string=} appId
* @param {Array<u2f.RegisterRequest>} registerRequests
* @param {Array<u2f.RegisteredKey>} registeredKeys
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
* @param {number=} opt_timeoutSeconds
*/
u2f.register = function(appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
if (js_api_version === undefined) {
// Send a message to get the extension to JS API version, then send the actual register request.
u2f.getApiVersion(
function (response) {
js_api_version = response['js_api_version'] === undefined ? 0: response['js_api_version'];
console.log("Extension JS API Version: ", js_api_version);
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
callback, opt_timeoutSeconds);
});
} else {
// We know the JS API version. Send the actual register request in the supported API version.
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
callback, opt_timeoutSeconds);
}
};
/**
* Dispatches register requests to available U2F tokens. An array of sign
* requests identifies already registered tokens.
* @param {string=} appId
* @param {Array<u2f.RegisterRequest>} registerRequests
* @param {Array<u2f.RegisteredKey>} registeredKeys
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
* @param {number=} opt_timeoutSeconds
*/
u2f.sendRegisterRequest = function(appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
u2f.getPortSingleton_(function(port) {
var reqId = ++u2f.reqCounter_;
u2f.callbackMap_[reqId] = callback;
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
var req = u2f.formatRegisterRequest_(
appId, registeredKeys, registerRequests, timeoutSeconds, reqId);
port.postMessage(req);
});
};
/**
* Dispatches a message to the extension to find out the supported
* JS API version.
* If the user is on a mobile phone and is thus using Google Authenticator instead
* of the Chrome extension, don't send the request and simply return 0.
* @param {function((u2f.Error|u2f.GetJsApiVersionResponse))} callback
* @param {number=} opt_timeoutSeconds
*/
u2f.getApiVersion = function(callback, opt_timeoutSeconds) {
u2f.getPortSingleton_(function(port) {
// If we are using Android Google Authenticator or iOS client app,
// do not fire an intent to ask which JS API version to use.
if (port.getPortType) {
var apiVersion;
switch (port.getPortType()) {
case 'WrappedIosPort_':
case 'WrappedAuthenticatorPort_':
apiVersion = 1.1;
break;
default:
apiVersion = 0;
break;
}
callback({ 'js_api_version': apiVersion });
return;
}
var reqId = ++u2f.reqCounter_;
u2f.callbackMap_[reqId] = callback;
var req = {
type: u2f.MessageTypes.U2F_GET_API_VERSION_REQUEST,
timeoutSeconds: (typeof opt_timeoutSeconds !== 'undefined' ?
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC),
requestId: reqId
};
port.postMessage(req);
});
};
@@ -0,0 +1,157 @@
/* globals $, urls, updateEnabled */
(function () {
var origData;
var setupButtonClickOnRefreshedProperties = function () {
$('#formRefreshCAS button').on('click', function (e) {
e.preventDefault();
// Show the refreshModal
var myModal = $('#refreshModal').modal({
keyboard: false,
backdrop: 'static'
});
var primaryButton = myModal.find('.modal-footer button.btn-primary');
// Disable the primary button
primaryButton.prop('disabled', true).text('Refreshing...');
$.post(e.target.parentNode.action, function (data) {
if (data.length !== 0) {
$('#refreshModal-label').text('Refreshed Properties');
myModal.find('.modal-content .modal-body').html(
'<pre>' + data + '</pre>' +
'<p>Click &quot;OK&quot; to reload page.</p>'
);
} else {
myModal.find('.modal-header .modal-title').text('Properties Refreshed');
myModal.find('.modal-content .modal-body').html(
'<p>Click &quot;OK&quot; to reload page.</p>'
);
}
})
.done(function () {
primaryButton.prop('disabled', false).text('Reload page').on('click', function (e) {
e.preventDefault();
window.location.reload();
});
})
.fail(function (jqXHR) {
$('#refreshModal-label').text('Problem With Refreshing Properties');
myModal.find('.modal-content .modal-body').html(
'<div class="alert alert-warning"><strong>Status: ' + jqXHR.status + '</strong><p/>Unable to refresh the properties. Please try again.</div>'
);
primaryButton.prop('disabled', false).text('OK').on('click', function (e) {
e.preventDefault();
myModal.modal('hide');
});
});
});
};
var createDataTable = function () {
$('#viewConfigsTable').DataTable({
'autoWidth': false,
'initComplete': function (settings, json) {
if (!json) {
$('#loadingMessage').hide();
$('#viewConfigError').show();
$('#view-configuration').hide();
} else {
$('#loadingMessage').hide();
$('#viewConfigError').hide();
$('#view-configuration').show();
}
},
'drawCallback': function () {
var api = this.api();
if (api.page.info().pages > 1) {
$('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'block';
} else {
$('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'none';
}
if (updateEnabled) {
editTable();
}
},
'processing': true,
'ajax': {
'url': urls.getConfiguration,
'dataSrc': function (json) {
var returnData = [];
for (var item in json) {
returnData.push({
'key': '<code>' + item + '</code>',
'value': '' + json[item] + ''
});
}
return returnData;
}
},
'columns': [
{'data': 'key', 'className': 'col-xs-6 key'},
{'data': 'value', 'className': 'col-xs-6 value'}
],
'pageLength': 50
});
};
var getRowData = function (row) {
var tds = row.find('td');
var tmp = {};
$.each(tds, function (i) {
if (i % 2 === 0) {
tmp.key = $(this).text();
} else {
tmp.value = $(this).text();
}
});
return tmp;
};
var editTable = function () {
$('#viewConfigsTable').editableTableWidget({editor: $('<textarea>')});
$('#viewConfigsTable td').on('focus', function () {
origData = getRowData($(this).closest('tr'));
});
$('#viewConfigsTable tr').on('change', function () {
var newChanges = getRowData($(this));
var data = {old: origData, new: newChanges};
$.ajax({url: urls.updateConfiguration, data: JSON.stringify(data), type: 'POST', contentType: 'application/json'})
.fail(function () {
var result = 'Failed to save settings.';
$('#alertWrapper').addClass('alert-warning');
$('#alertWrapper').removeClass('alert-success');
$('#alertWrapper').text(result);
$('#alertWrapper').show();
})
.success(function () {
var result = 'Saved settings successfully.';
$('#alertWrapper').removeClass('alert-warning');
$('#alertWrapper').addClass('alert-success');
$('#resultText').text(result);
$('#alertWrapper').show();
});
});
};
// initialization *******
(function init () {
createDataTable();
setupButtonClickOnRefreshedProperties();
})();
// Public Methods
return {
/**
* Not used
*/
};
})();
@@ -0,0 +1,136 @@
$('.ui.search').search({
type: 'message',
searchDelay: 500,
silent: true,
apiSettings: {
silent: true,
cache: false,
url: urls.search,
onResponse: function (casResp) {
var response = {
results: {}
};
for (var key in casResp) {
if (casResp.hasOwnProperty(key)) {
var prop = casResp[key];
var group = prop.group;
if (response.results[group] === undefined) {
response.results[group] = {
name: group,
results: []
};
}
response.results[group].results.push({
title: prop.id,
description: prop.description,
defaultValue: prop.defaultValue,
type: prop.type,
deprecated: prop.deprecated,
requiredProperty: prop.requiredProperty,
requiredModule: prop.requiredModule,
requiredModuleAutomated: prop.requiredModuleAutomated
});
}
}
return response;
},
},
minCharacters: 3,
templates: {
message: function (response, type) {
var html = '';
$('#accordion').empty();
if (type === 'empty') {
html += '<h3><i class=\'fa fa-search\' />&nbsp;<strong>No Results</strong></h3>';
html += '<div class=\'alert alert-warning\'>';
html += '<i class=\'fa fa-exclamation-circle\'/>&nbsp;';
html += 'No search results could be found based on the provided query.';
html += '</div>';
}
for (var group in response.results) {
var modules = new Set();
html += '<h2><i class=\'fa fa-users\' />&nbsp;<strong>Group: </strong>' + group + '</h2>';
var props = response.results[group].results;
html += '<div>';
for (var i = 0; i < props.length; i++) {
html += '<p>';
var prop = props[i];
html += '<i class=\'fa fa-cogs\'/>&nbsp;';
html += 'Property: <code>' + prop.title + '=' + prop.defaultValue + '</code><br/>';
if (prop.deprecated) {
html += '<p/><div class=\'alert alert-warning\'>';
html += '<i class=\'fa fa-exclamation-circle\'/>&nbsp;';
html += 'This property is deprecated and will be removed in future CAS versions.';
html += '</div>';
}
if (prop.requiredProperty) {
html += '<p/><div class=\'alert alert-success\'>';
html += '<i class=\'fa fa-check-square\'/>&nbsp;';
html += 'This property is required.';
html += '</div>';
}
html += '<i class=\'fab fa-codepen\' />&nbsp;Type: <code>' + prop.type + '</code><br/>';
if (prop.description != null) {
html += '<p>' + prop.description + '</p>';
}
if (prop.requiredModule != null) {
modules.add(prop.requiredModule);
}
html += '<hr>';
}
if (modules.size > 0) {
html += '<div>';
html += '<p><i class=\'fa fa-gear\' />&nbsp;Required Modules</p>';
html += '<ul class=\'nav nav-pills\'>';
html += '<li class=\'active\'><a href=\'#1\' data-toggle=\'tab\'>Maven</a></li>';
html += '<li><a href=\'#2\' data-toggle=\'tab\'>Gradle</a></li>';
html += '</ul>';
for (let moduleString of modules) {
html += '<div class=\'tab-content\'>';
var moduleArr = moduleString.split('|');
var module = moduleArr[0];
var maven = '&lt;dependency&gt;\n';
maven += '\t&lt;groupId&gt;org.apereo.cas&lt;/groupId&gt;\n';
maven += '\t&lt;artifactId&gt;' + module + '&lt;/artifactId&gt;\n';
maven += '\t&lt;cas.version&gt;${cas.version}&lt;/cas.version&gt;\n';
maven += '&lt;/dependency&gt;\n';
html += '<div class=\'tab-pane active\' id=\'1\'><pre>' + maven + '</pre></div>';
var gradle = 'compile \'org.apereo.cas:' + module + ':${project.\'cas.version\'}\'\n';
html += '<div class=\'tab-pane\' id=\'2\'><pre>' + gradle + '</pre></div>';
html += '</div>';
}
html += '</div>';
}
html += '</div>';
}
html += '</div>';
$('#accordion').html(html);
$('#accordion').accordion({
heightStyle: 'content'
});
$('#accordion').accordion('refresh');
return '';
}
}
});