webmaker.org/routes/badges.js

397 строки
12 KiB
JavaScript

var BadgeClient = require('badgekit-api-client');
var async = require('async');
module.exports = function (env) {
// Error messages
var errorHandlers = {
unauthorized: function () {
var err = new Error('You must be logged in to access this area.');
err.status = 401;
return err;
},
forbidden: function () {
var errorString = 'You are not authorized to access this area. ' +
'If you think you are supposed to have permissions, ' +
'try logging out and in again, or contact help@webmaker.org';
var err = new Error(errorString);
err.status = 403;
return err;
}
};
var badgeClient = new BadgeClient(env.get('BADGES_ENDPOINT'), {
key: env.get('BADGES_KEY'),
secret: env.get('BADGES_SECRET')
});
var permissionsModel = require('../lib/badges-permissions-model.js');
return {
middleware: {
// Check if a use has at least a certain level of permissions
// Can be 'admin', 'superMentor' or 'mentor'
atleast: function (level) {
var levels = ['isAdmin', 'isSuperMentor', 'isMentor'];
return function (req, res, next) {
var user = req.session.user;
if (!level || levels.indexOf(level) <= -1) {
var problem = level + ' is not a valid type of user.';
var err = new Error('There is a problem with the permissions model: ' + problem);
return next(err);
} else if (!user) {
return next(errorHandlers.unauthorized());
} else if (user.isAdmin) {
return next();
} else if (level === 'isSuperMentor' && (user.isAdmin || user.isSuperMentor)) {
return next();
} else if (level === 'isMentor' && (user.isAdmin || user.isSuperMentor || user.isMentor)) {
return next();
} else {
return next(errorHandlers.forbidden());
}
};
},
// Does this user have permissions to issue, approve applications, see instances?
hasPermissions: function (action) {
return function (req, res, next) {
var user = req.session.user;
if (!user) {
return next(errorHandlers.unauthorized());
}
var allowed = permissionsModel({
badge: req.params.badge,
user: req.session.user,
action: action
});
if (!allowed) {
return next(errorHandlers.forbidden());
} else {
return next();
}
};
}
},
getAll: function (req, res, next) {
badgeClient.getBadges({
system: env.get('BADGES_SYSTEM')
}, function (err, badges) {
if (err) {
return res.send(500, err.message);
}
res.json(badges);
});
},
getBadge: function (req, res, next) {
badgeClient.getBadge({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge
}, function (err, data) {
if (err) {
return res.send(500, err.message);
}
return res.send(data);
});
},
getInstances: function (req, res, next) {
badgeClient.getBadgeInstances({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge
}, function (err, instances) {
// errorString
if (err) {
return res.send(500, err.message);
}
// We need to get the badge data too
badgeClient.getBadge({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge
}, function (err, badge) {
if (err) {
return res.send(500, err.message);
}
res.json({
badge: badge,
instances: instances
});
});
});
},
deleteInstance: function (req, res, next) {
badgeClient.deleteBadgeInstance({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
email: req.params.email
}, function (err, result) {
if (err) {
console.log(err.stack);
return res.send(500, err.message);
}
res.send('DELETED');
});
},
details: function (req, res, next) {
function getBadge(callback) {
badgeClient.getBadge({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge
}, function (err, data) {
return callback(err, data);
});
}
function getInstance(callback) {
if (req.session.user) {
badgeClient.getBadgeInstance({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
email: req.session.user.email
}, function (err, data) {
if (err && err.name === 'ResourceNotFoundError') {
err = null;
}
return callback(err, data);
});
} else {
return callback(null, null);
}
}
function getApplication(callback) {
if (req.session.user) {
badgeClient.getApplications({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge
}, {
email: req.session.user.email,
processed: false
}, function (err, data) {
return callback(err, data);
});
} else {
return callback(null, null);
}
}
async.parallel(
[getBadge, getInstance, getApplication],
function (err, results) {
if (err) {
return res.render('badge-not-found.html', {
page: 'search',
view: 'badges'
});
}
var badge = results[0];
var instance = results[1];
var application = (results[2] && results[2].length) ? results[2][0] : null;
// Shim for https://bugzilla.mozilla.org/show_bug.cgi?id=1001161
if (badge.issuer && !badge.issuer.imageUrl) {
badge.issuer.imageUrl = 'https://webmaker.org/img/logo-webmaker.png';
}
// Can the current user issue this badge?
var canIssue = permissionsModel({
badge: req.params.badge,
user: req.session.user,
action: 'issue'
});
// Do we want to ask which Hive city the earner is affiliated with?
var requestCity = (req.params.badge === 'hive-community-member');
// Check if we have any criteria to display.
var canApply = true;
if (['Data Trail Timeline', 'Privacy Coach', 'IP Address Tracer'].indexOf(badge.name) >= 0) {
canApply = false;
}
res.render('badge-detail.html', {
page: req.params.badge,
view: 'badges',
badge: badge,
canIssue: canIssue,
canApply: canApply,
requestCity: requestCity,
backpackUrl: env.get('BACKPACK_PUSH_URL'),
assertionUrl: instance ? instance.assertionUrl : null,
application: application
});
});
},
apply: function (req, res, next) {
var evidence = [req.body.evidence];
var applicationSlug = req.body.applicationSlug;
if (req.body.city) {
evidence.push('Hive City: ' + req.body.city);
}
evidence = evidence.map(function (evidence) {
return {
reflection: evidence
};
});
var application = {
learner: req.session.user.email,
evidence: evidence,
slug: applicationSlug
};
var apiFunction;
if (applicationSlug) {
apiFunction = badgeClient.updateApplication.bind(badgeClient);
} else {
apiFunction = badgeClient.addApplication.bind(badgeClient);
}
apiFunction({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
application: application
}, function (err, data) {
if (err) {
return res.send(500, err);
}
res.send(data);
});
},
issue: function (req, res, next) {
var apiFunction;
var query = {
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
comment: req.body.comment
};
if (req.body.emails) {
query.emails = req.body.emails;
apiFunction = badgeClient.createBadgeInstances.bind(badgeClient);
} else if (req.body.email) {
query.email = req.body.email;
apiFunction = badgeClient.createBadgeInstance.bind(badgeClient);
} else {
return res.send(500, {
error: 'No email address provided'
});
}
apiFunction(query, function (err, data) {
if (err) {
var errorString = err.toString();
return res.send(500, {
error: errorString
});
}
res.send(data);
});
},
claim: function (req, res, next) {
var codeQuery = {
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
claimCode: req.body.claimcode
};
badgeClient.claimClaimCode(codeQuery, req.session.user.email, function (err, data) {
if (err) {
var errorString = err.message;
if (err.code === 404) {
errorString = 'The code "' + req.body.claimcode + '" could not be found';
}
return res.send(500, {
error: errorString
});
}
var instanceQuery = {
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
email: req.session.user.email
};
badgeClient.createBadgeInstance(instanceQuery, function (err, data) {
if (err) {
var errorString = err.message;
return res.send(500, errorString);
}
res.send(data);
});
});
},
getApplications: function (req, res, next) {
badgeClient.getApplications({
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge
}, function (err, raw) {
if (err) {
return res.send(500, err.message);
}
var applications = [];
// No way to query for pending applications only.
// See bug 1021009
if (req.query.processed) {
applications = raw;
} else {
raw.forEach(function (application) {
if (!application.processed) {
applications.push(application);
}
});
}
res.send(applications);
});
},
submitReview: function (req, res, next) {
var context = {
system: env.get('BADGES_SYSTEM'),
badge: req.params.badge,
application: req.params.application,
review: {
author: req.session.email,
comment: req.body.comment,
reviewItems: req.body.reviewItems
}
};
badgeClient.addReview(context, function (err, review) {
if (err) {
return res.send(500, err.message);
}
return res.send(200, 'Success');
});
},
create: function (req, res, next) {
var context = {
system: env.get('BADGES_SYSTEM'),
badge: req.body
};
badgeClient.createBadge(context, function (err, badge) {
if (err) {
return res.send(500, err.message);
}
return res.send(200, badge);
});
},
update: function (req, res, next) {
var context = {
system: env.get('BADGES_SYSTEM'),
badge: req.body
};
badgeClient.updateBadge(context, function (err, badge) {
if (err) {
return res.send(500, err.message);
}
return res.send(200, badge);
});
}
};
};