|
| 1 | +'use strict'; |
| 2 | +var async = require('async'); |
| 3 | +var _ = require('lodash'); |
| 4 | + |
| 5 | +/** |
| 6 | + * Webhook handler to award badges based on courses |
| 7 | + * Courses "Code" must correspond to the badge slug |
| 8 | + * @param {Object} certificate contains all the info, header/user/course passed |
| 9 | + * ie: {"header":{"source":"LearnUpon","version":1,"webhookId":2213843,"attempt":2,"lastAttemptAt":"2016-09-01T10:33:32Z","webHookType":"course_completion","signature":"5736605a1627415455de6f7ca50e7e9d"},"user":{"userId":12345,"lastName":null,"firstName":null,"email":"qq@example.com","username":null,"customData":null},"enrollmentId":42,"courseId":42,"courseName":"CoderDojo Ethos: Implementation and Practice","courseReferenceCode":"coderdojo-ethos:-implementation-and-practice","courseMetaData":null,"modules":[{"id":42,"type":"scorm","name":"CoderDojo Ethos: Implementation and Practice","status":"passed","percentage":100.0,"dateCompleted":null,"attempts":null,"isKnowledgeCheck":false}],"credits":[],"courseAccessExpiresAt":null,"certification":false,"certificationName":null,"certExpiresAt":null,"wasRecertified":false,"dateEnrolled":"2016-08-29T12:02:38Z","dateStarted":"2016-09-01T10:30:50Z","dateCompleted":"2016-09-01T10:32:28Z","percentage":100,"enrollmentStatus":"passed","hasAttemptsRemaining":false} |
| 10 | + */ |
| 11 | +function awardLMSBadge (args, cb) { |
| 12 | + var seneca = this; |
| 13 | + var plugin = args.role; |
| 14 | + var certif = args; |
| 15 | + var user = certif.user; |
| 16 | + |
| 17 | + function checkTestStatus (waterfallCb) { |
| 18 | + if (certif.header.webHookType !== 'course_completion') { |
| 19 | + return cb(null, {ok: false, why: 'Unhandled webhook'}); |
| 20 | + } |
| 21 | + if (!_.every(certif.modules, {'status': 'passed'}) && |
| 22 | + !_.every(certif.modules, {'status': 'completed'}) && |
| 23 | + !_.includes(['completed', 'passed'], certif.enrollmentStatus) ) { |
| 24 | + return cb(null, {ok: false, why: 'Unhandled status'}); |
| 25 | + } |
| 26 | + waterfallCb(null, certif.courseReferenceCode); |
| 27 | + } |
| 28 | + |
| 29 | + function getBadge (badgeName, waterfallCb) { |
| 30 | + seneca.act({role: 'cd-badges', cmd: 'getBadge', slug: badgeName}, |
| 31 | + function (err, badge) { |
| 32 | + if (err) return cb(err); |
| 33 | + waterfallCb(null, badge); |
| 34 | + }); |
| 35 | + } |
| 36 | + |
| 37 | + function getUser (badge, waterfallCb) { |
| 38 | + seneca.act({role: 'cd-users', cmd: 'list', query: {lmsId: user.userId}}, |
| 39 | + function (err, sysUser) { |
| 40 | + if (err) return cb(err); |
| 41 | + if (_.isEmpty(sysUser)) return cb(null, {ok: false, why: 'LMSUser not found'}); |
| 42 | + return waterfallCb(null, sysUser[0], badge); |
| 43 | + }); |
| 44 | + } |
| 45 | + |
| 46 | + function awardBadge (sysUser, badge, waterfallCb) { |
| 47 | + var applicationData = { |
| 48 | + user: sysUser, |
| 49 | + badge: badge.badge, |
| 50 | + emailSubject: 'You have been awarded a new CoderDojo digital badge!' |
| 51 | + }; |
| 52 | + seneca.act({role: 'cd-badges', cmd: 'sendBadgeApplication', |
| 53 | + applicationData: applicationData, |
| 54 | + user: {id: null} |
| 55 | + }, |
| 56 | + function (err, user) { |
| 57 | + if (err) return cb(err); |
| 58 | + waterfallCb(); |
| 59 | + }); |
| 60 | + } |
| 61 | + |
| 62 | + |
| 63 | + async.waterfall([ |
| 64 | + checkTestStatus, |
| 65 | + getBadge, |
| 66 | + getUser, |
| 67 | + awardBadge |
| 68 | + ], cb); |
| 69 | + |
| 70 | +} |
| 71 | + |
| 72 | +module.exports = awardLMSBadge; |
0 commit comments