From 61a090a86d891357b8276af1d98900508bfc5500 Mon Sep 17 00:00:00 2001 From: Mike Larsson Date: Wed, 29 May 2013 16:39:24 -0400 Subject: [PATCH 1/2] Adding basic claim code confirmation screen --- controllers/backpack.js | 43 ++++++++++++++++++++++++++----- openbadger.js | 28 ++++++++++++++++----- views/claim.html | 56 ++++++++++++++++++++++++++++------------- 3 files changed, 98 insertions(+), 29 deletions(-) diff --git a/controllers/backpack.js b/controllers/backpack.js index 86d709e..c4c353b 100644 --- a/controllers/backpack.js +++ b/controllers/backpack.js @@ -13,22 +13,53 @@ module.exports = function (app) { if (!claimCode) return res.render('claim.html'); + claimCode = claimCode.trim(); - openbadger.claim({ - code: claimCode.trim(), + openbadger.getBadgeFromCode({ + code: claimCode, email: user.email }, function(err, data) { if (err) { - if (err.code === 404 && err.message === 'unknown claim code') + if (err.code === 404) req.flash('error', "That claim code appears to be invalid."); else if (err.code === 409) - req.flash('warn', "You already have that badge."); + req.flash('warn', "You have already used that claim code."); else - req.flash('error', "Unable to claim badge."); + req.flash('error', "A problem was encountered."); + return res.render('claim.html', { + code: claimCode + }); } else { - req.flash('success', 'Badge claimed!'); + return res.render('claim.html', { + code: claimCode, + badge: data.badge + }); } + }); + + }); + + app.post('/claim', function (req, res, next) { + var claimCode = req.query.code; + var user = res.locals.user; + + if (!user) { + return res.redirect('/login'); + } + + openbadger.claim({ + code: claimCode, + email: user.email + }, function(err, data) { + console.log(err, data); + if (err) + if (err.code === 409) + req.flash('warn', "You already have that badge."); + else + req.flash('error', "There has been an error claiming your badge."); + else + req.flash('success', "You've claimed a new badge!"); return res.redirect('/backpack'); }); diff --git a/openbadger.js b/openbadger.js index 647f00f..fde7365 100644 --- a/openbadger.js +++ b/openbadger.js @@ -62,6 +62,14 @@ function filterBadges(data, query) { return data; } +function getJWTToken(email) { + var claims = { + prn: email, + exp: Date.now() + TOKEN_LIFETIME + }; + return jwt.encode(claims, JWT_SECRET); +} + var openbadger = new Api(ENDPOINT, { getBadges: { @@ -138,16 +146,24 @@ var openbadger = new Api(ENDPOINT, { }); }, + getBadgeFromCode: function getBadgeFromCode (query, callback) { + var email = query.email; + var code = query.code; + var params = { + auth: getJWTToken(email), + email: email, + code: code, + }; + this.get('/unclaimed', { qs: params }, function(err, data) { + return callback(err, data); + }); + }, + claim: function claim (query, callback) { var email = query.email; var code = query.code; - var claims = { - prn: email, - exp: Date.now() + TOKEN_LIFETIME - }; - var token = jwt.encode(claims, JWT_SECRET); var params = { - auth: token, + auth: getJWTToken(email), email: email, code: code, }; diff --git a/views/claim.html b/views/claim.html index d4ae7f4..20c0ed2 100644 --- a/views/claim.html +++ b/views/claim.html @@ -3,22 +3,44 @@ {% set navItem = 'claim' %} {% block content %} -

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+ {% if badge %} +
+
+ +
+
+

{{ badge.name }}

+
+ + +
+
+
+ +
+
+
+
+
+
+ {% else %} +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

-

Already have a claim code?

-
-
-
- -
- -
-
-
-
- -
-
-
-
+

Already have a claim code?

+
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+ {% endif %} {% endblock %} \ No newline at end of file From bb29e2964cbad47ee026d00ad655eda074f65e30 Mon Sep 17 00:00:00 2001 From: Mike Larsson Date: Wed, 29 May 2013 20:12:01 -0400 Subject: [PATCH 2/2] Adding claim model to handle badge claim requests and approval process --- controllers/backpack.js | 38 +++++++++++++-------- models/claim.js | 73 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 models/claim.js diff --git a/controllers/backpack.js b/controllers/backpack.js index c4c353b..bf72cbe 100644 --- a/controllers/backpack.js +++ b/controllers/backpack.js @@ -1,4 +1,6 @@ const openbadger = require('../openbadger'); +const db = require('../db'); +const claim = db.model('Claim'); module.exports = function (app) { @@ -48,21 +50,31 @@ module.exports = function (app) { return res.redirect('/login'); } - openbadger.claim({ + claim.findOrCreate({ code: claimCode, - email: user.email - }, function(err, data) { - console.log(err, data); - if (err) - if (err.code === 409) - req.flash('warn', "You already have that badge."); - else - req.flash('error', "There has been an error claiming your badge."); - else - req.flash('success', "You've claimed a new badge!"); - return res.redirect('/backpack'); + LearnerId: user.id + }).complete(function(err, claim) { + if (err) { + return next(err); + } + else { + claim.submit(function(err, claim){ + if (err) { + if (err.code === 409) + req.flash('warn', "You already have that badge."); + else + req.flash('error', "There has been an error claiming your badge."); + } + else { + if (claim.state === 'waiting') + req.flash('info', "Your badge claim is awaiting approval from your parent or guardian."); + else + req.flash('success', "You've claimed a new badge!"); + } + return res.redirect('/backpack'); + }); + } }); - }); app.get('/backpack', function (req, res, next) { diff --git a/models/claim.js b/models/claim.js new file mode 100644 index 0000000..55a6e0d --- /dev/null +++ b/models/claim.js @@ -0,0 +1,73 @@ +const openbadger = require('../openbadger'); +const db = require('../db'); + +module.exports = { + properties: { + id: { + type: db.type.INTEGER, + primaryKey: true, + autoIncrement: true + }, + code: { + type: db.type.STRING, + allowNull: false + }, + state: { + type: db.type.ENUM, + values: [ + 'waiting', // The claimed badge is waiting for guardian approval (where applicable) + 'approved', // The claimed badge has been approved by guardian for issuing + 'denied' // The claimed badge has been denied by guardian + ], + defaultValue: 'waiting', + allowNull: false + } + }, + relationships: [ + { + model: 'Learner', + type: 'belongsTo' + } + ], + instanceMethods: { + submit: function (force, callback) { + if (typeof force === 'function') { + callback = force; + force = false; + } + + var claim = this; + + claim.getLearner().complete(function (err, learner) { + if (err || !learner) + return callback(err); + + if (learner.underage && !force) { + return claim.updateAttributes({ + state: 'waiting' + }).complete(callback); + } + + openbadger.claim({ + code: claim.code, + email: learner.email + }, function (err, data) { + if (err) + return callback(err); + claim.updateAttributes({ + state: 'approved' + }).complete(callback); + }); + + }); + }, + approve: function (callback) { + this.submit(true, callback); + }, + deny: function (callback) { + claim.updateAttributes({ + state: 'denied' + }).complete(callback); + } + } +};