Skip to content
Snippets Groups Projects
eccs.js 13.53 KiB
// Needed to draw the ECCS2 DataTable
var table;
var url = "/eccs/api/eccsresults?eccsdt=1";
var infoCircle = '<a href="https://wiki.geant.org/display/eduGAIN/eduGAIN+Connectivity+Check#eduGAINConnectivityCheck-Statusesandresults"><i class="fas fa-info-circle"></i></a>';

/*
 * Secure Hash Algorithm (SHA1)
 * https://www.webtoolkit.info/javascript_sha1.html
*/
function SHA1(msg) {
   function rotate_left(n,s) {
      var t4 = ( n<<s ) | (n>>>(32-s));
      return t4;
   };
   function lsb_hex(val) {
      var str='';
      var i;
      var vh;
      var vl;
      for( i=0; i<=6; i+=2 ) {
         vh = (val>>>(i*4+4))&0x0f;
         vl = (val>>>(i*4))&0x0f;
         str += vh.toString(16) + vl.toString(16);
      }
      return str;
   };
   function cvt_hex(val) {
      var str='';
      var i;
      var v;
      for( i=7; i>=0; i-- ) {
         v = (val>>>(i*4))&0x0f;
         str += v.toString(16);
      }
      return str;
   };
   function Utf8Encode(string) {
      string = string.replace(/\r\n/g,'\n');
      var utftext = '';
      for (var n = 0; n < string.length; n++) {
         var c = string.charCodeAt(n);
         if (c < 128) {
            utftext += String.fromCharCode(c);
         }
         else if((c > 127) && (c < 2048)) {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
         }
         else {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
         }
      }
      return utftext;
   };
   var blockstart;
   var i, j;
   var W = new Array(80);
   var H0 = 0x67452301;
   var H1 = 0xEFCDAB89;
   var H2 = 0x98BADCFE;
   var H3 = 0x10325476;
   var H4 = 0xC3D2E1F0;
   var A, B, C, D, E;
   var temp;
   msg = Utf8Encode(msg);
   var msg_len = msg.length;
   var word_array = new Array();
   for( i=0; i<msg_len-3; i+=4 ) {
      j = msg.charCodeAt(i)<<24 | msg.charCodeAt(i+1)<<16 |
      msg.charCodeAt(i+2)<<8 | msg.charCodeAt(i+3);
      word_array.push( j );
   }
   switch( msg_len % 4 ) {
      case 0:
         i = 0x080000000;
         break;
      case 1:
         i = msg.charCodeAt(msg_len-1)<<24 | 0x0800000;
         break;
      case 2:
         i = msg.charCodeAt(msg_len-2)<<24 | msg.charCodeAt(msg_len-1)<<16 | 0x08000;
         break;
      case 3:
         i = msg.charCodeAt(msg_len-3)<<24 | msg.charCodeAt(msg_len-2)<<16 | msg.charCodeAt(msg_len-1)<<8 | 0x80;
         break;
   }
   word_array.push( i );
   while( (word_array.length % 16) != 14 ) word_array.push( 0 );
   word_array.push( msg_len>>>29 );
   word_array.push( (msg_len<<3)&0x0ffffffff );
   for ( blockstart=0; blockstart<word_array.length; blockstart+=16 ) {
      for( i=0; i<16; i++ ) W[i] = word_array[blockstart+i];
      for( i=16; i<=79; i++ ) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
      A = H0;
      B = H1;
      C = H2;
      D = H3;
      E = H4;
      for( i= 0; i<=19; i++ ) {
         temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
         E = D;
         D = C;
         C = rotate_left(B,30);
         B = A;
         A = temp;
      }
      for( i=20; i<=39; i++ ) {
         temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
         E = D;
         D = C;
         C = rotate_left(B,30);
         B = A;
         A = temp;
      }
      for( i=40; i<=59; i++ ) {
         temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
         E = D;
         D = C;
         C = rotate_left(B,30);
         B = A;
         A = temp;
      }
      for( i=60; i<=79; i++ ) {
         temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
         E = D;
         D = C;
         C = rotate_left(B,30);
         B = A;
         A = temp;
      }
      H0 = (H0 + A) & 0x0ffffffff;
      H1 = (H1 + B) & 0x0ffffffff;
      H2 = (H2 + C) & 0x0ffffffff;
      H3 = (H3 + D) & 0x0ffffffff;
      H4 = (H4 + E) & 0x0ffffffff;
   }
   var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
   return temp.toLowerCase();
}


// PHP Variables retrieved from eccs.php
// idp (entityID of the IdP)
// date (date time of the check)
// reg_auth (the IdP RegistrationAuthority)
// status (the ECCS IdP Status)
// check_result (the ECCS check result)
if (date) {
   url = url.concat("&date=" + date);
}
if (reg_auth) {
   url = url.concat("&reg_auth=" + reg_auth);
}
if (idp) {
   url = url.concat("&idp=" + idp);
}
if (status) {
   url = url.concat("&status=" + status);
}
if (check_result) {
   url = url.concat("&check_result=" + check_result);
}

function getPastResults() {
   let checkDate = $.datepicker.formatDate("yy-mm-dd", $('#datepicker').datepicker().datepicker('getDate'));
   let getUrl = window.location;
   let baseUrl = getUrl.protocol + "//" + getUrl.host + "/";
   let dataSource = baseUrl + "/eccs/api/eccsresults?eccsdt=1&date=" + checkDate;
   $('.loader').css('display','block');
   table.clear().draw();
   table.ajax.url(dataSource).load(hideLoder);
   function hideLoder() {
       $('.loader').css('display','none');
   } 
}

// use URL constructor and return hostname
function getHostname(url) {
   if (url == ""){
      return null
   }
   const urlNew = new URL(url);
   if (urlNew.hostname){
      return urlNew.hostname;
   }
   else {
      return url.replace(/.+:/g, '');
   }
}

function getCheckResult(checkResult){
   if (checkResult == "OK"){
      return '<div class="tooltip">OK <span class="tooltiptext tooltip-top tooltip-ok">The IdP is consuming correctly the SP metadata and returns a valid login page</span></div> '+infoCircle;
   }
   else if (checkResult == "Timeout"){
      return '<div class="tooltip">Timeout <span class="tooltiptext tooltip-top tooltip-timeout">The IdP does not load a valid login page within 60 seconds</span></div> '+infoCircle;
   }
   else if (checkResult == "Unable-To-Check"){
      return '<div class="tooltip">Unable To Check <span class="tooltiptext tooltip-top tooltip-unable-to-check">The IdP can\'t be checked</span></div> '+infoCircle;
   }
   else if (checkResult == "Connection-Error"){
      return '<div class="tooltip">Connection Error <span class="tooltiptext tooltip-top tooltip-connection-error">Check failed due a connection error</span></div> '+infoCircle;
   }
   else if (checkResult == "No-SP-Metadata-Error"){
      return '<div class="tooltip">No-SP-Metadata-Error <span class="tooltiptext tooltip-top tooltip-no-sp-metadata-error">The IdP is not consuming correctly the SP metadata</span></div> '+infoCircle
   }
   else if (checkResult == "IdP-Generic-Error"){
      return '<div class="tooltip">IdP-Generic-Error <span class="tooltiptext tooltip-top tooltip-idp-generic-error">The IdP reported an error</span></div> '+infoCircle
   }
   else if (checkResult == "403-Forbidden"){
      return '<div class="tooltip">403-Forbidden <span class="tooltiptext tooltip-top tooltip-403-forbidden">The IdP reported a "403 Forbidden" error</span></div> '+infoCircle
   }
   else if (checkResult == "SSL-Error"){
      return '<div class="tooltip">SSL-Error <span class="tooltiptext tooltip-top tooltip-ssl-error">The IdP has a problem on its SSL certificate</span></div> '+infoCircle;
   }
   else if (checkResult == "DISABLED"){
      return '<div class="tooltip">Disabled <span class="tooltiptext tooltip-top tooltip-disabled">The check has been disabled for the IdP</span></div> '+infoCircle;
   }
   else{
      return checkResult;
   }
}

/* Formatting function for row details - modify as you need */
function format ( d ) {
    // `d` is the original data object for the row
    return '<table id="inner-table">'+
        '<tr>'+
            '<td class="strong">IdP DisplayName:</td>'+
            '<td>'+d.displayName+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td class="strong">Technical Contacts:</td>'+
            '<td>'+d.contacts.technical+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td class="strong">Support Contacts:</td>'+
            '<td>'+d.contacts.support+'</td>'+
            '<td class="strong">Check Time</td>'+
            '<td class="strong">Check Result</td>'+
            //'<td class="strong">HTTP Code</td>'+
            '<td class="strong">Page Source</td>'+
            '<td class="strong">Retry Check</td>'+
        '</tr>'+
        '<tr>'+
            '<td class="strong">SP1:</td>'+
            '<td>https://'+getHostname(d.sp1.entityID)+'</td>'+
            '<td>'+d.sp1.checkTime+'</td>'+
            '<td>'+getCheckResult(d.sp1.checkResult)+'</td>'+
            //'<td>'+d.sp1.httpCode+'</td>'+
            '<td><a href="/eccs/html/'+d.date+'/'+SHA1(d.entityID)+'---'+getHostname(d.sp1.entityID)+'.html" target="_blank">Click to open</a></td>'+
            '<td><a href="/eccs/api/getsamlreq?idp='+d.entityID+'&sp='+d.sp1.entityID+'" target="_blank">Click to retry</a></td>'+
        '</tr>'+
        '<tr>'+
            '<td class="strong">SP2:</td>'+
            '<td>https://'+getHostname(d.sp2.entityID)+'</td>'+
            '<td>'+d.sp2.checkTime+'</td>'+
            '<td>'+getCheckResult(d.sp2.checkResult)+'</td>'+
            //'<td>'+d.sp2.httpCode+'</td>'+
            '<td><a href="/eccs/html/'+d.date+'/'+SHA1(d.entityID)+'---'+getHostname(d.sp2.entityID)+'.html" target="_blank">Click to open</a></td>'+
            '<td><a href="/eccs/api/getsamlreq?idp='+d.entityID+'&sp='+d.sp2.entityID+'" target="_blank">Click to retry</a></td>'+
        '</tr>'+
        '<tr>'+
            '<td class="strong">SP3:</td>'+
            '<td>https://'+getHostname(d.sp3.entityID)+'</td>'+
            '<td>'+d.sp3.checkTime+'</td>'+
            '<td>'+getCheckResult(d.sp3.checkResult)+'</td>'+
            //'<td>'+d.sp3.httpCode+'</td>'+
            '<td><a href="/eccs/html/'+d.date+'/'+SHA1(d.entityID)+'---'+getHostname(d.sp3.entityID)+'.html" target="_blank">Click to open</a></td>'+
            '<td><a href="/eccs/api/getsamlreq?idp='+d.entityID+'&sp='+d.sp3.entityID+'" target="_blank">Click to retry</a></td>'+
        '</tr>'+
    '</table>';
}

$(document).ready(function() {
    // Setup - add a text input to each footer cell
    $('#eccstable thead tr').clone(true).appendTo( '#eccstable thead' );
    $('#eccstable thead tr:not(:eq(1)) th').each( function (i) {
        var title = $('#eccstable thead th').eq( $(this).index() ).text();
        if($(this).index() !=0 && $(this).index() !=5) $(this).html( '<input type="text" placeholder="Search '+title+'" style="text-align:center;width: 100%;" />' );
 
        $( 'input', this ).on( 'keyup change', function () {
            if ( table.column(i).search() !== this.value ) {
                table
                    .column(i)
                    .search( this.value )
                    .draw();
            }
        } );
    } );

    table = $('#eccstable').DataTable( {
        "responsive": "true",
        "ajax": { 
           "url": url,
           "dataSrc": ""
        },
        "lengthMenu": [[10, 30, 50, 100, -1], [10, 30, 50, 100, "All"]],
        "autoWidth": false,
        "dom": '<"top"lip>rt<"bottom"><"clear">',
        "columns": [
            {
              "className":      'details-control',
              "orderable":      false,
              "data":           null,
              "defaultContent": ''
            },
            { 
              "data": "displayName",
              "defaultContent": ''
            },
            { "data": "entityID" },
            { "data": "registrationAuthority" },
            { 
              "data": "date",
              "width": "180px",
              "className": "dt-body-center",
              "visible": false
            },
            { 
              "data": "status",
              "className": "dt-body-center",
              "visible": false
            }
        ],
        "rowCallback": function( row, data, index ) {
          if (data.status == "ERROR") {
            //$('td', row).css('background-color', '#EA4335'); // NEW ECCS2
            $('td', row).css('background-color', '#EA3D3F'); // OLD ECCS
            //$('td', row).css('background-color', '#FF0000');
            //$('td', row).css('background-color', '#F22422');
          }
          if (data.status == "DISABLED") {
            $('td', row).css('background-color', '#FFFFFF');
          }
          if (data.status == "OK") {
            //$('td', row).css('background-color', '#34A853');
            //$('td', row).css('background-color', '#00CE00'); // NEW ECCS2
            $('td', row).css('background-color', '#72F81B'); // OLD ECCS
          }
          if (data.status == "UNKNOWN") {
            $('td', row).css('background-color', '#FFDB58');
          }

        },
        "order": [[1, 'asc']]
    } );
     
    // Add event listener for opening and closing details
    $('#eccstable tbody').on('click', 'td.details-control', function () {
        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()) ).show();
            tr.addClass('shown');
        }
    } );

    $('input:checkbox').on('change', function () {
       //build a regex filter string with an or(|) condition
       var sts = $('input:checkbox[name="status"]:checked').map(function() {
          return this.value;
       }).get().join('|');

       //filter in column 5, with an regex, no smart filtering, not case sensitive
       table.column(5).search(sts, true, false, false).draw(false);
    });
} );