diff --git a/README.md b/README.md index 9a8fe08..95d5ede 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,24 @@ and viewed in `cover_html/index.html`. The coverage tool used is [node-cover][], see its documentation for details. + +### Command line tool + +Once installed, you can validate a badge URL at the command line: + +``` +$ node bin/openbadges-validate +usage: openbadges-validate assertion [spec_version] [verification_type] + + assertion: URL, JWS signature or JSON representation + + spec_version: The target specification, allowed values: "0.5.0", "1.0.0", "1.1.0" + (Omit or use "auto" for auto-detect) + + verification_type: The target verification type, allowed values: "hosted", "signed" + (Omit or use "auto" for auto-detect) +``` + [jake]: https://github.com/mde/jake [node-cover]: https://github.com/itay/node-cover diff --git a/bin/openbadges-validate b/bin/openbadges-validate new file mode 100755 index 0000000..016d88c --- /dev/null +++ b/bin/openbadges-validate @@ -0,0 +1,72 @@ +#!/usr/bin/env node +var validator = require('../'); +var args = process.argv.slice(2); +var assertion = args[0] || ''; +var specVersion = args[1] || ''; +var verificationType = args[2] || ''; + +function usage() { + console.log("usage: openbadges-validate assertion [spec_version] [verification_type]"); + console.log(''); + console.log(' assertion: URL, JWS signature or JSON representation'); + console.log(''); + console.log(' spec_version: The target specification, allowed values: "0.5.0", "1.0.0", "1.1.0"'); + console.log(' (Omit or use "auto" for auto-detect)'); + console.log(''); + console.log(' verification_type: The target verification type, allowed values: "hosted", "signed"'); + console.log(' (Omit or use "auto" for auto-detect)'); + console.log(''); +} + +(function main () { + if (assertion.length) { + if (specVersion.length == 0 || specVersion == 'auto') { + specVersion = undefined; + } + else { + if (['1.1.0', '1.0.0', '0.5.0'].indexOf(specVersion) === -1) { + usage(); + process.exit(1); + } + } + if (verificationType.length == 0 || verificationType == 'auto') { + verificationType = undefined; + } + else { + if (['hosted', 'signed'].indexOf(verificationType) === -1) { + usage(); + process.exit(1); + } + } + console.log('assertion: ' + assertion); + console.log('spec_version: ' + (specVersion || '')); + console.log('verification_type: ' + (verificationType || '')); + console.log('--------------------------------'); + validator.validate(assertion, handleResponse, specVersion, verificationType); + } + else { + usage(); + process.exit(1); + } +})(); + +function handleResponse (err, data) { + if (err === null) { + console.log('Okay'); + process.exit(0); + } + if (err instanceof Error) { + console.log('Error:'); + if (err.name && err.message) { + console.log(err.name + ': ' + err.message); + } + if (err.reason) { + console.log('└── ' + err.reason); + } + process.exit(1); + } + console.log('Error details:'); + console.log(err); + console.log(data); + process.exit(1); +} diff --git a/index.js b/index.js index 69a8907..9b92527 100644 --- a/index.js +++ b/index.js @@ -362,6 +362,10 @@ function validate(input, callback) { return validate.validateSigned(input, callback); if (isUrl(input)) return validate.validateHostedUrl(input, callback); + if (isJson(input)) + var url = urlFromAssertion(JSON.parse(input)); + if (url) + return validate.validateHostedUrl(url, callback, ''); return callback(makeError('input', 'not a valid signed badge or url', { input: input })); } return callback(makeError('input', 'input must be a string or object', { input: input })); @@ -541,6 +545,19 @@ function getInternalClass(thing) { return Object.prototype.toString.call(thing); } +function isJson (str) { + try { JSON.parse(str); return true } catch(e) { return false } +} + +function urlFromAssertion (json) { + try { + var url = json.verify.url; + if (isUrl(url)) + return url; + return false; + } catch(e) { return false; } +} + const isUrl = regexToValidator(re.url, 'must be a URL'); const isAbsoluteUrl = regexToValidator(re.absoluteUrl, 'must be an absolute URL'); const isEmail = regexToValidator(re.email, 'must be an email address'); @@ -725,3 +742,4 @@ validate.doesHashedEmailMatch = doesHashedEmailMatch; validate.VALID_HASHES = VALID_HASHES; validate.validateOldInterdependentFields = validateOldInterdependentFields; validate.validateInterdependentFields = validateInterdependentFields; +validate.validate = validate; \ No newline at end of file