public
Last active

Open Badges Issuer Gadget for Google Sites - More info http://mashe.hawksey.info/2012/12/open-badges-issuer-gadget-google-sites

  • Download Gist
Google Form Assertion publisher.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
// initialising some of these as blank to to keep human readable structure
var badgeTemplate = {
"recipient": "",
"salt": "",
"evidence": "",
"issued_on": "",
"badge": {
"version": "0.1.0",
"name": "",
"image": "",
"description": "",
"criteria": "",
"issuer": {
"origin": "http://mashe.hawksey.info",
"name": "Martin Hawksey",
"org": "CETIS",
"contact": "app@hawksey.info"
}
}
};
 
function onFormSumbit(e) {
// next three lines used to get last row number (might fail on simulatious form submits but will do for thsi project)
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheet = doc.getSheetByName("DATA");
var lastrow = sheet.getLastRow();
var correct = false; // initialise the response to the question as incorrect
// next 4 lines read the form values submitted
var timestamp = e.values[0];
var email = e.values[1];
var name = e.values[2];
var resp = e.values[3];
 
var claim_code = []; // initialise an array of claim_codes
var baseUrl = "https://sites.google.com/a/hawksey.info/sandbox/openbadges"; //this is where my site is hosted
var claim_code_base = "row=" + lastrow; // our claim code is going to carry two pieces of info row number and type of badge
claim_code.push(Utilities.base64Encode(claim_code_base + "&type=user")); //everyone gets a user badge so we push this to our claim_code array encoding the value to disguise
// next 4 lines tests if user got the answer right and if so adds a claim_code
if (resp == ScriptProperties.getProperty("answer")){ // answer hidden as script property
claim_code.push(Utilities.base64Encode(claim_code_base + "&type=gold"));
correct = true;
}
var url = baseUrl+"?claim_code=" + claim_code.join(","); // build the url to be emailed to person. If multiple badges the claim_code is comma seperated
// compose text for the email
var emailText = "Hi "+name+",\nThanks for trying the Open Badges Issuer Gadget. To claim you badges visit \n\n" + url;
if (correct) {
emailText += "\n\n [As you got the question right you can claim the Issuer Gadget User and Gold badges]";
} else {
emailText += "\n\n [Unfortunately you didn't attempt the optional question or got it wrong but you can still claim you Issuer Gadget User badge]";
}
// using the MailApp function of Apps Script to send the email to the person
MailApp.sendEmail(email, "Claim your Open Badges Issuer Gadget Badges", emailText);
}
 
// this function builds the Assertion JSON blob for each badge
// the code is Published > Deployed as web app. To see an example render visit:
// https://script.google.com/a/macros/hawksey.info/s/AKfycbxnZUexQevCm_drrhKsYe5RdwCqE8bRkVDsmfT9b48/exec?claim_code=cm93PTImdHlwZT11c2Vy
// An issue with this is currently Google prevent cross domain access to the json file via ajax (which the issuer api uses) so the response is currently proxied using php
// <?php
// $binfo = json_decode(file_get_contents('https://script.google.com/a/macros/hawksey.info/s/AKfycbyO221yQaOb0kvZJQndKu48FFfBS3bspP6s0w7rPSvW_swo37c/exec?claim_code='.$_GET['claim_code']));
// header('Content-Type: application/json');
// echo json_encode($binfo);
// ?>
// try at http://hawksey.info/labs/gadget_proxy.php?claim_code=cm93PTImdHlwZT11c2Vy
function doGet(e){
// The flow here is get the data from the spreadsheet and create the assertion blob
// Other ways of doing this use native NoSQL style ScriptDb (part of Apps Script), pre baking assertion
// then serving up directly in doGet
// to access spreadsheet data we need to get by id (stored by runing setup)
var doc = SpreadsheetApp.openById(ScriptProperties.getProperty('active'));
var sheet = doc.getSheetByName("DATA");
var claim_encode = Utilities.base64Decode(e.parameter.claim_code); // decode claim_code
var claim_code = bin2String(claim_encode); // need to convert byte array to string
var data = getQueryString("?"+claim_code); // extract row and type passed in claim_code
// if question was answered correctly prepare gold badge
if (data.type == "gold"){
var select ="*"; // used as part of evidence
var name = "Open Badges Issuer Gadget Gold";
var image = "https://lh3.googleusercontent.com/-59t5UJTspPw/ULjMmXmB12I/AAAAAAAABoY/5l6Ee6uVVvo/s800/openbadgesgadgetgold.png";
var description = "Awared for understanding urls required to use use the Open Badges Issuer Gadget emebed in a Google Site.";
} else {
var select ="A,B"; // used as part of evidence
var name = "Open Badges Issuer Gadget User";
var image = "https://lh5.googleusercontent.com/-B8zpcTV0OTg/ULjMmPyIZVI/AAAAAAAABoU/8i87MPmpN2M/s800/openbadgesgadgetpart.png";
var description = "Awarded for trying the Open Badges Issuer Gadget.";
}
// get some data recorded in the spreadsheet
var timestamp = sheet.getRange(data.row, 1).getValue();
var email = sheet.getRange(data.row, 2).getValue();
// publishing form response in another spreadsheet (using IMPORTRANGE) which lets us query
var evidence_base = "https://spreadsheets.google.com/tq?tqx=out:html&key=0ApRGZfrjxtuedFlmVHJ5RjBPVWxpSUg3djc5VFR1WVE";
// fill in the badge assertion details
badgeTemplate.salt = "G00g1e";
badgeTemplate.recipient = hashEmailAddress(email, badgeTemplate.salt);
badgeTemplate.evidence = evidence_base + "&tq="+encodeURIComponent("select "+select+" where A = datetime '"+Utilities.formatDate(timestamp, "GMT", "yyyy-MM-dd HH:mm:ss")+"'");
badgeTemplate.issued_on = Utilities.formatDate(timestamp, "GMT", "yyyy-MM-dd");
badgeTemplate.badge.name = name;
badgeTemplate.badge.image = image;
badgeTemplate.badge.description = description;
badgeTemplate.badge.criteria = "http://mashe.hawksey.info/2012/12/open-badges-issuer-gadget-google-sites";
// now that Assertion is complete next lines publish it to the web
var output = ContentService.createTextOutput();
output.setMimeType(ContentService.MimeType.JSON);
output.setContent(JSON.stringify(badgeTemplate));
return output;
}
 
function setup(){
ScriptProperties.setProperty('active', SpreadsheetApp.getActiveSpreadsheet().getId());
}
 
// Based on https://github.com/mozilla/openbadges/wiki/How-to-hash-&-salt-in-various-languages.
function hashEmailAddress(email, salt) {
var hash = CryptoJS.SHA256(email+salt);
return 'sha256$'+ hash;
}
 
// Modification of http://stackoverflow.com/a/647272/1027723
function getQueryString(ref) {
var qs= ref.split('?');
var result = {}, queryString = qs[1],
re = /([^&=]+)=([^&]*)/g, m;
while (m = re.exec(queryString)) {
result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
return result;
}
 
// From http://stackoverflow.com/a/3195961/1027723
function bin2String(array) {
return String.fromCharCode.apply(String, array);
}
gistfile1.xml
XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Open Badges Issuer Gadget" width="800" height="700" author="Martin Hawksey"
description="This gadget allows you to integrate the the Mozilla Open Badges Issuer API into Google Sites. To use insert into a Google site and set a base url for your hosted assertions. To allow users to collect their badges direct them to the web address of the Site page containing the gadget adding ?claim_code={insert the rest of their assertion url} to the url"
author_email="apps@hawksey.info" scrolling="true"
title_url="http://mashe.hawksey.info" author_affiliation="http://mashe.hawksey.info"
screenshot="https://lh3.googleusercontent.com/-TqTcrKbb1dg/ULy8Iyb318I/AAAAAAAABo8/uZId4bI5G5s/s800/gadget-screenshot-280.png"
thumbnail="https://lh5.googleusercontent.com/-cBAUZxwrM4A/ULy8IzXNlyI/AAAAAAAABpA/-dB90Stogww/s800/gadget-screenshot-120.png"/>
<UserPref name="script_url" display_name="Base Url" datatype="string" default_value="" required="true"/>
<Content type="html">
<![CDATA[ <script src="https://beta.openbadges.org/issuer.js"></script>
<script type="text/javascript">
<!--
var code = []; // initialize assesor array
var prefs = new gadgets.Prefs();
// Modification of http://stackoverflow.com/a/647272/1027723/
function getQueryString() {
var ref = document.referrer;
var qs= ref.split('?');
var result = {}, queryString = qs[1],
re = /([^&=]+)=([^&]*)/g, m;
while (m = re.exec(queryString)) {
result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
return result;
}
function init() {
var base_url = prefs.getString("script_url");
var codes = getQueryString().claim_code;
code = codes.split(",");
if (codes != "") {
for ( var i = 0; i < code .length; i++ ) {
code[i] = base_url + code[i];
}
document.getElementById("collectBadge").style.display='block';
document.getElementById("msg").style.display='none';
}
}
gadgets.util.registerOnLoadHandler(init);
// -->
</script>
<p id="msg">No claim code</p>
<p id="collectBadgeWrapper"><a href='javascript:void(0);' onclick='OpenBadges.issue(code, function(errors, successes)
{ });' id="collectBadge" style="display:none">Claim your badge</a>
</p> ]]>
</Content>
</Module>
‚Äč

I would like to use your badging gadget, but does this script still work with the new way forms and responses are handled in Google Drive now?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.