diff --git a/api.js b/api.js index 749df6f..3af9e0b 100644 --- a/api.js +++ b/api.js @@ -40,6 +40,7 @@ var galleryRouter = require('./routes/gallery/index'); var projectRouter = require('./routes/project/index'); var userRouter = require('./routes/user/index'); var uploadRouter = require('./routes/upload/index'); +var badgeRouter = require('./routes/badge/index'); api.use('/tutorial', tutorialRouter); api.use('/share', shareRouter); @@ -47,6 +48,7 @@ api.use('/gallery', galleryRouter); api.use('/project', projectRouter); api.use('/user', userRouter); api.use('/upload', uploadRouter); +api.use('/badge', badgeRouter); // catch 404 and forward to error handler api.use(function(req, res, next) { diff --git a/models/tutorial.js b/models/tutorial.js index 5c9a20d..a984a48 100644 --- a/models/tutorial.js +++ b/models/tutorial.js @@ -43,6 +43,14 @@ const TutorialSchema = new mongoose.Schema( type: String, required: true, }, + badgeId: { + type: String, + required: false, + }, + issuerId: { + type: String, + required: false, + }, steps: [ { type: StepSchema, diff --git a/package.json b/package.json index a444c19..cc8ff49 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "docs": "apidoc -i . -e \"docs\" \"(node_modules)\" -o docs" }, "dependencies": { + "@geobadges/badgr-api-client": "^0.12.0", "chalk": "^4.1.0", "cookie-parser": "~1.4.4", "cors": "^2.8.5", @@ -25,5 +26,8 @@ "request": "^2.88.2", "uuid": "^8.3.2", "uuidv4": "^6.2.12" + }, + "devDependencies": { + "nodemon": "^2.0.15" } } diff --git a/routes/badge/grantBadge.js b/routes/badge/grantBadge.js new file mode 100644 index 0000000..6b52ef6 --- /dev/null +++ b/routes/badge/grantBadge.js @@ -0,0 +1,59 @@ +// jshint esversion: 8 +// jshint node: true +"use strict"; + +const API = require("@geobadges/badgr-api-client"); + +const badgesClient = new API({ + endpoint: process.env.BADGES_ENDPOINT, + username: process.env.BADGES_USERNAME, + password: process.env.BADGES_PASSWORD, +}); + +/** + * @api {post} /grant Grant a badge + * @apiName grandBadge + * @apiDescription Grant a badge to a user. + * @apiGroup Badge + * + * @apiParam {String} email Users Email + * @apiParam {String} badgeClassEntityId ID of the badge class + * @apiParam {boolean} createNotification User receives an email notification + * @apiParam {String} issuerEntityId ID of the issuer + * + * @apiSuccess (Success 200) {String} message `Badge granted successfully.` + * @apiError (On error) {Obejct} 500 Complications when granting badge + */ +const grantBadge = async (req, res) => { + try { + const { email, badgeClassEntityId, createNotification, issuerEntityId } = req.body; + + if (!email) { + return res.status(400).send({ + message: "email missing", + }); + } + + const status = await badgesClient.grant({ + badgeClassEntityId, + createNotification, + email, + issuerEntityId, + }); + + if (!status) { + throw new Error("Could not grant badge"); + } + + res.status(200).send({ + message: "Badge granted successfully.", + }); + } catch (err) { + console.log(err); + return res.status(500).send(err); + } +}; + +module.exports = { + grantBadge, +}; diff --git a/routes/badge/index.js b/routes/badge/index.js new file mode 100644 index 0000000..560cb92 --- /dev/null +++ b/routes/badge/index.js @@ -0,0 +1,10 @@ +// jshint esversion: 8 +// jshint node: true +"use strict"; + +var express = require("express"); +var BadgeRouter = express.Router(); + +BadgeRouter.route("/grant").post(require("./grantBadge").grantBadge); + +module.exports = BadgeRouter; diff --git a/routes/tutorial/postTutorial.js b/routes/tutorial/postTutorial.js index d0c7b67..01f80f4 100644 --- a/routes/tutorial/postTutorial.js +++ b/routes/tutorial/postTutorial.js @@ -66,6 +66,8 @@ const postTutorial = async function (req, res) { creator: req.user.email, title: req.body.title, steps: req.body.steps, + badgeId: req.body.badgeId, + issuerId: req.body.issuerId, }; // storing existing images in mongoDB req.files && diff --git a/routes/tutorial/putTutorial.js b/routes/tutorial/putTutorial.js index 9dc1bce..ca71ffd 100644 --- a/routes/tutorial/putTutorial.js +++ b/routes/tutorial/putTutorial.js @@ -9,6 +9,7 @@ const path = require("path"); const Tutorial = require("../../models/tutorial"); const User = require("../../models/user"); +const { update } = require("../../models/tutorial"); /** * @api {put} /tutorial/:tutorialId Update tutorial @@ -67,7 +68,10 @@ const putTutorial = async function (req, res) { if (owner === oldTutorial.creator) { var updatedTutorial = {}; updatedTutorial.title = req.body.title || oldTutorial.title; + updatedTutorial.badgeId = req.body.badgeId || oldTutorial.badgeId; + updatedTutorial.issuerId = req.body.issuerId || oldTutorial.issuerId; updatedTutorial.steps = req.body.steps || oldTutorial.steps; + // ensure that the requirement is not related to the tutorial itself if (updatedTutorial.steps[0].requirements) { updatedTutorial.steps[0].requirements =