зеркало из https://github.com/mozilla/CSOL-site.git
Merge pull request #318 from stenington/under-13-claims
Building out claim code process for <13
This commit is contained in:
Коммит
daaf7281d7
|
@ -1,4 +1,6 @@
|
|||
const openbadger = require('../openbadger');
|
||||
const db = require('../db');
|
||||
const claim = db.model('Claim');
|
||||
|
||||
module.exports = function (app) {
|
||||
|
||||
|
@ -13,27 +15,68 @@ 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
|
||||
});
|
||||
}
|
||||
return res.redirect('/backpack');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
app.post('/claim', function (req, res, next) {
|
||||
var claimCode = req.query.code;
|
||||
var user = res.locals.user;
|
||||
|
||||
if (!user) {
|
||||
return res.redirect('/login');
|
||||
}
|
||||
|
||||
claim.findOrCreate({
|
||||
code: claimCode,
|
||||
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) {
|
||||
var badges = [];
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -3,22 +3,44 @@
|
|||
{% set navItem = 'claim' %}
|
||||
|
||||
{% block content %}
|
||||
<p>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.</p>
|
||||
{% if badge %}
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<img src="{{ badge.image }}">
|
||||
</div>
|
||||
<div class="span8">
|
||||
<h3>{{ badge.name }}</h3>
|
||||
<form method="post" class="form-horizontal well">
|
||||
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
||||
<input type="hidden" id="input-code" name="code" value="{{ code }}">
|
||||
<fieldset>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn">Claim this badge</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>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.</p>
|
||||
|
||||
<h3>Already have a claim code?</h3>
|
||||
<form method="get" class="form-horizontal well span6 offset3">
|
||||
<fieldset>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="input-code">Claim Code</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="input-code" name="code" placeholder="e.g. AE198QPM">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn">Claim this badge</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<h3>Already have a claim code?</h3>
|
||||
<form method="get" class="form-horizontal well span6 offset3">
|
||||
<fieldset>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="input-code">Claim Code</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="input-code" name="code" placeholder="e.g. AE198QPM" value="{{ code }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn">Claim this badge</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock %}
|
Загрузка…
Ссылка в новой задаче