API Integration with HaveIBeenPwned w Structure and Template

We recently had a request for our users to be able to check if their email address has been a victim of a known data breach per the awesome API and data stores provided at https://haveibeenpwned.com/. Here is the API: https://haveibeenpwned.com/API/v2 and some background story of this project and why it's worthwhile. There are some already-written consumer examples shared there, but I chose to try and fashion a lightweight version of my own that could be quickly deployed to a Liferay page without developing an entire portlet for this goal.

I was able to achieve this utilizing Liferay Templates and Structures, JavaScript, Freemarker (or Velocity), HTML and CSS. I'll provide a few basic steps and enough (Freemarker) code to get you going. This mini-app greets the user and offers him/her to check their email address for known breaches. The code makes an AJAX call to the HaveIBeenPwned API and returns JSON data (if data is found) that is parsed and formatted for display in HTML / CSS. 

1) Create a simple structure. I named mine "PWNED". Add a text field (that we won't use) to it and save / publish it.

2) Create a (Freemarker) template. I named mine "PWNED". Attach this template to the "PWNED" structure from step 1. Uncheck the "Cacheable" option. Add the code below to the template, then Save / Publish it:

<#assign user = permissionChecker.getUser() />
<!DOCTYPE html>
<html>
<body>
<style>
.attention {
color: red;
}
.breachIntro {
font-size: 16px;
}
</style>
<h2>Hello, ${user.firstName}!</h2>
<p class="breachIntro">Check if your email address been victim of a known data breach:</p>
<form id="checkBreaches" name="checkBreaches">
<label for="Email">Email address:</label>
<input id="checkEmail" type="text" name="Email" value="" placeholder="${user.emailAddress}">
<input type="submit" name="submit" value="Check It!" onclick="loadDoc();return false;">
<p><a href="#" onclick='reloadMe();'>Refresh Page / Search Again</a></p>
</form>
<div id="breachInfo"></div>
<script>
function loadDoc() {
  var xhttp = new XMLHttpRequest();
  var url =  "https://haveibeenpwned.com/api/v2/breachedaccount/";
  if (document.getElementById("checkEmail").value == "") {
  var email = "${user.emailAddress}";
  }
  else {
    var email = document.getElementById("checkEmail").value;
  }
  var checkUserURL = url + email;
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
      writeData(xhttp.responseText);
    }
    else if (xhttp.readyState == 4 && xhttp.status == 404){
    document.getElementById("breachInfo").innerHTML = "<h4><p>404 - No data returned for  <span class=\"attention\">\"" + email + ".\"</span> This is a good thing! It appears you have no known associated breaches with this account.</p></h4>";
    }
  };
  xhttp.open("GET", checkUserURL, true);
  xhttp.send();
}
function writeData(response) {
var arr = JSON.parse(response);
var i;
var email = document.getElementById("checkEmail").value;
var out = "<h4><span class=\"attention\">Unfortunately, it looks like \"" + email + "\" has been breached. </span>Please see the details below:</h4>" + "<div class=\"breachEntries\">";
for(i = 0; i < arr.length; i++) {
        out += "<div class=\"breachEntry\" id=\"breachEntry" + i + "\"><div class=\"breachDomain\"><strong>Domain of Breach:&nbsp;</strong>" + arr[i].Name +
        "&nbsp;(<a href=\"http://" + arr[i].Domain + "\" target=\"_blank\"><strong>http://" + arr[i].Domain + "</a></strong>):&nbsp;" +
        "</div><div class=\"breachDesc\">" +
        arr[i].Description +
        "</div><div class=\"breachItems\"><strong>Breached Items:&nbsp;</strong>" +
        arr[i].DataClasses +
        "</div><div class=\"breachDate\"><strong>Breach Date:&nbsp;</strong>" +
        arr[i].BreachDate +
        "</div></div><hr>";
        }
    out += "</div>";
document.getElementById("breachInfo").innerHTML = out;
}
function reloadMe() {
window.location = window.location.pathname;
}
</script>
<div>(Courtesy of "<a href="https://haveibeenpwned.com/" target="_blank">https://haveibeenpwned.com/</a>" and Daniel Tyger for the Liferay steps / code.)
</div>
</body>
</html>
3) Create a web content object, using the newly-created structure / template combination from steps 1-2. Publish / save it and deploy it to a Liferay page. You should see something like the following:
If you enter "foo@bar.com" into the "Email address" field, you will see what the data results look like when parsed...:

and - a look at the resulting HTML:

You could easily paint a table, instead, and include other fields from the API I have omitted in this example...

Explanation of the code:

1) Create the Freemarker "user" variable we will utilize to display the user's first name and email address where we need it later in the app...:

<#assign user = permissionChecker.getUser() />
....
<h2>Hello, ${user.firstName}!</h2>
...
var email = "${user.emailAddress}";

2) Create the form and the <div> for displaying the results:

<form id="checkBreaches" name="checkBreaches">
<label for="Email">Email address:</label>
<input id="checkEmail" type="text" name="Email" value="" placeholder="${user.emailAddress}">
<input type="submit" name="submit" value="Check It!" onclick="loadDoc();return false;">
<p><a href="/group/mycampus/identity-theft">Refresh Page / Search Again</a></p>
</form>
<div id="breachInfo"></div>

3) Set up the forked AJAX function call  to the API to use either the Liferay user emailAddress or the one entered by the user into the form and to write a success message if no data is returned:

function loadDoc() ...

and upon successful data results, fire the writeData function:

    if (xhttp.readyState == 4 && xhttp.status == 200) {
      writeData(xhttp.responseText);
    }

4) Parse the results for display in the writeData() function:

function writeData(response) {
var arr = JSON.parse(response);
var i;
var email = document.getElementById("checkEmail").value;
var out = "<h4><span class=\"attention\">Unfortunately, it looks like \"" + email + "\" has been breached. </span>Please see the details below:</h4>" + "<div class=\"breachEntries\">";
for(i = 0; i < arr.length; i++) {
        out += "<div class=\"breachEntry\" id=\"breachEntry" + i + "\"><div class=\"breachDomain\"><strong>Domain of Breach:&nbsp;</strong>" + arr[i].Name +
        "&nbsp;(<a href=\"http://" + arr[i].Domain + "\" target=\"_blank\"><strong>http://" + arr[i].Domain + "</a></strong>):&nbsp;" +
        "</div><div class=\"breachDesc\">" +
        arr[i].Description +
        "</div><div class=\"breachItems\"><strong>Breached Items:&nbsp;</strong>" +
        arr[i].DataClasses +
        "</div><div class=\"breachDate\"><strong>Breach Date:&nbsp;</strong>" +
        arr[i].BreachDate +
        "</div></div><hr>";
        }
    out += "</div>";
document.getElementById("breachInfo").innerHTML = out;
}

Hope it works for you. Please respond if it does not. Suggestions welcome. It's brand new for me...