diff --git a/constants/general.constant.js b/constants/general.constant.js index 77af8a5e..dd0385b9 100644 --- a/constants/general.constant.js +++ b/constants/general.constant.js @@ -69,7 +69,11 @@ const REQUEST_TYPES = { //Define names of the roles specifically associated with permission to create an account const POST_ROLES = {}; POST_ROLES[HACKER] = "postHacker"; -POST_ROLES[SPONSOR] = "postSponsor"; +POST_ROLES[SPONSOR_T1] = "postSponsor"; +POST_ROLES[SPONSOR_T2] = "postSponsor"; +POST_ROLES[SPONSOR_T3] = "postSponsor"; +POST_ROLES[SPONSOR_T4] = "postSponsor"; +POST_ROLES[SPONSOR_T5] = "postSponsor"; POST_ROLES[VOLUNTEER] = "postVolunteer"; POST_ROLES[STAFF] = "postStaff"; diff --git a/constants/role.constant.js b/constants/role.constant.js index b33aa36e..752ca1f3 100644 --- a/constants/role.constant.js +++ b/constants/role.constant.js @@ -69,6 +69,7 @@ const sponsorT1Role = { "routes": [ Constants.Routes.sponsorRoutes.post, Constants.Routes.sponsorRoutes.getSelfById, + Constants.Routes.sponsorRoutes.getSelf, ] }; @@ -78,6 +79,7 @@ const sponsorT2Role = { "routes": [ Constants.Routes.sponsorRoutes.post, Constants.Routes.sponsorRoutes.getSelfById, + Constants.Routes.sponsorRoutes.getSelf, ] }; @@ -87,6 +89,7 @@ const sponsorT3Role = { "routes": [ Constants.Routes.sponsorRoutes.post, Constants.Routes.sponsorRoutes.getSelfById, + Constants.Routes.sponsorRoutes.getSelf, ] }; @@ -96,6 +99,7 @@ const sponsorT4Role = { "routes": [ Constants.Routes.sponsorRoutes.post, Constants.Routes.sponsorRoutes.getSelfById, + Constants.Routes.sponsorRoutes.getSelf, ] }; @@ -105,6 +109,7 @@ const sponsorT5Role = { "routes": [ Constants.Routes.sponsorRoutes.post, Constants.Routes.sponsorRoutes.getSelfById, + Constants.Routes.sponsorRoutes.getSelf, ] }; diff --git a/constants/routes.constant.js b/constants/routes.constant.js index fbeb9f6c..3f00db2c 100644 --- a/constants/routes.constant.js +++ b/constants/routes.constant.js @@ -127,6 +127,10 @@ const hackerRoutes = { }; const sponsorRoutes = { + "getSelf": { + requestType: Constants.REQUEST_TYPES.GET, + uri: "/api/sponsor/self/", + }, "getSelfById": { requestType: Constants.REQUEST_TYPES.GET, uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.SELF, diff --git a/docs/api/api_data.js b/docs/api/api_data.js index c7806fac..a7a4b40e 100644 --- a/docs/api/api_data.js +++ b/docs/api/api_data.js @@ -1797,6 +1797,67 @@ define({ "url": "https://api.mchacks.ca/api/hacker/resume/:id" }] }, + { + "type": "get", + "url": "/sponsor/self", + "title": "get information about logged in sponsor", + "name": "self", + "group": "Hacker", + "version": "1.4.1", + "success": { + "fields": { + "Success 200": [{ + "group": "Success 200", + "type": "String", + "optional": false, + "field": "message", + "description": "
Success message
" + }, + { + "group": "Success 200", + "type": "Object", + "optional": false, + "field": "data", + "description": "Sponsor object
" + } + ] + }, + "examples": [{ + "title": "Success-Response: ", + "content": "{\n \"message\": \"Successfully retrieved sponsor information\", \n \"data\": {...}\n }", + "type": "object" + }] + }, + "error": { + "fields": { + "Error 4xx": [{ + "group": "Error 4xx", + "type": "String", + "optional": false, + "field": "message", + "description": "Error message
" + }, + { + "group": "Error 4xx", + "type": "Object", + "optional": false, + "field": "data", + "description": "empty
" + } + ] + }, + "examples": [{ + "title": "Error-Response: ", + "content": "{\"message\": \"Sponsor not found\", \"data\": {}}", + "type": "object" + }] + }, + "filename": "routes/api/sponsor.js", + "groupTitle": "Hacker", + "sampleRequest": [{ + "url": "https://api.mchacks.ca/api/sponsor/self" + }] + }, { "type": "get", "url": "/hacker/self", diff --git a/docs/api/api_data.json b/docs/api/api_data.json index 51be9836..6a1d94b3 100644 --- a/docs/api/api_data.json +++ b/docs/api/api_data.json @@ -1796,6 +1796,67 @@ "url": "https://api.mchacks.ca/api/hacker/resume/:id" }] }, + { + "type": "get", + "url": "/sponsor/self", + "title": "get information about logged in sponsor", + "name": "self", + "group": "Hacker", + "version": "1.4.1", + "success": { + "fields": { + "Success 200": [{ + "group": "Success 200", + "type": "String", + "optional": false, + "field": "message", + "description": "Success message
" + }, + { + "group": "Success 200", + "type": "Object", + "optional": false, + "field": "data", + "description": "Sponsor object
" + } + ] + }, + "examples": [{ + "title": "Success-Response: ", + "content": "{\n \"message\": \"Successfully retrieved sponsor information\", \n \"data\": {...}\n }", + "type": "object" + }] + }, + "error": { + "fields": { + "Error 4xx": [{ + "group": "Error 4xx", + "type": "String", + "optional": false, + "field": "message", + "description": "Error message
" + }, + { + "group": "Error 4xx", + "type": "Object", + "optional": false, + "field": "data", + "description": "empty
" + } + ] + }, + "examples": [{ + "title": "Error-Response: ", + "content": "{\"message\": \"Sponsor not found\", \"data\": {}}", + "type": "object" + }] + }, + "filename": "routes/api/sponsor.js", + "groupTitle": "Hacker", + "sampleRequest": [{ + "url": "https://api.mchacks.ca/api/sponsor/self" + }] + }, { "type": "get", "url": "/hacker/self", diff --git a/docs/api/api_project.js b/docs/api/api_project.js index 0cd83632..3b66e564 100644 --- a/docs/api/api_project.js +++ b/docs/api/api_project.js @@ -1,16 +1,16 @@ -define({ - "name": "hackerAPI", - "version": "0.0.8", - "description": "Documentation for the API used for mchacks", - "defaultVersion": "0.0.8", - "title": "hackerAPI documentation", - "url": "https://api.mchacks.ca/api", - "sampleUrl": "https://api.mchacks.ca/api", - "apidoc": "0.3.0", - "generator": { - "name": "apidoc", - "time": "2019-01-10T23:24:21.462Z", - "url": "http://apidocjs.com", - "version": "0.17.7" - } +define({ + "name": "hackerAPI", + "version": "0.0.8", + "description": "Documentation for the API used for mchacks", + "defaultVersion": "0.0.8", + "title": "hackerAPI documentation", + "url": "https://api.mchacks.ca/api", + "sampleUrl": "https://api.mchacks.ca/api", + "apidoc": "0.3.0", + "generator": { + "name": "apidoc", + "time": "2019-01-18T19:02:31.941Z", + "url": "http://apidocjs.com", + "version": "0.17.7" + } }); \ No newline at end of file diff --git a/docs/api/api_project.json b/docs/api/api_project.json index 8ad885dc..8c20a67c 100644 --- a/docs/api/api_project.json +++ b/docs/api/api_project.json @@ -1,16 +1,16 @@ -{ - "name": "hackerAPI", - "version": "0.0.8", - "description": "Documentation for the API used for mchacks", - "defaultVersion": "0.0.8", - "title": "hackerAPI documentation", - "url": "https://api.mchacks.ca/api", - "sampleUrl": "https://api.mchacks.ca/api", - "apidoc": "0.3.0", - "generator": { - "name": "apidoc", - "time": "2019-01-10T23:24:21.462Z", - "url": "http://apidocjs.com", - "version": "0.17.7" - } +{ + "name": "hackerAPI", + "version": "0.0.8", + "description": "Documentation for the API used for mchacks", + "defaultVersion": "0.0.8", + "title": "hackerAPI documentation", + "url": "https://api.mchacks.ca/api", + "sampleUrl": "https://api.mchacks.ca/api", + "apidoc": "0.3.0", + "generator": { + "name": "apidoc", + "time": "2019-01-18T19:02:31.941Z", + "url": "http://apidocjs.com", + "version": "0.17.7" + } } \ No newline at end of file diff --git a/middlewares/sponsor.middleware.js b/middlewares/sponsor.middleware.js index a6f93dca..48193523 100644 --- a/middlewares/sponsor.middleware.js +++ b/middlewares/sponsor.middleware.js @@ -87,6 +87,39 @@ async function validateConfirmedStatus(req, res, next) { } } +/** + * Finds the sponsor information of the logged in user + * @param {{user: {id: string, accountType: string}}} req + * @param {*} res + * @param {(err?)=>void} next + */ +async function findSelf(req, res, next) { + if (!Constants.General.SPONSOR_TIERS.includes(req.user.accountType)) { + return next({ + status: 409, + message: Constants.Error.ACCOUNT_TYPE_409_MESSAGE, + error: { + id: req.user.id + } + }); + } + + const sponsor = await Services.Sponsor.findByAccountId(req.user.id); + + if (!!sponsor) { + req.body.sponsor = sponsor; + return next(); + } else { + return next({ + status: 404, + message: Constants.Error.SPONSOR_404_MESSAGE, + error: { + id: req.user.id + } + }); + } +} + /** * @async * @function findById @@ -157,6 +190,7 @@ async function checkDuplicateAccountLinks(req, res, next) { module.exports = { parsePatch: parsePatch, parseSponsor: parseSponsor, + findSelf: Middleware.Util.asyncMiddleware(findSelf), findById: Middleware.Util.asyncMiddleware(findById), createSponsor: Middleware.Util.asyncMiddleware(createSponsor), checkDuplicateAccountLinks: Middleware.Util.asyncMiddleware(checkDuplicateAccountLinks), diff --git a/routes/api/sponsor.js b/routes/api/sponsor.js index 01a18778..427f573b 100644 --- a/routes/api/sponsor.js +++ b/routes/api/sponsor.js @@ -25,6 +25,41 @@ module.exports = { activate: function (apiRouter) { const sponsorRouter = new express.Router(); + /** + * @api {get} /sponsor/self get information about logged in sponsor + * @apiName self + * @apiGroup Hacker + * @apiVersion 1.4.1 + * + * @apiSuccess {String} message Success message + * @apiSuccess {Object} data Sponsor object + * @apiSuccessExample {object} Success-Response: + * { + "message": "Successfully retrieved sponsor information", + "data": { + "id": "5bff4d736f86be0a41badb91", + "accountId": "5bff4d736f86be0a41badb99", + "tier": 3, + "company": "companyName", + "contractURL": "https://www.contractHere.com", + "nominees": ["5bff4d736f86be0a41badb93","5bff4d736f86be0a41badb94"] + } + } + + * @apiError {String} message Error message + * @apiError {Object} data empty + * @apiErrorExample {object} Error-Response: + * {"message": "Sponsor not found", "data": {}} + * @apiPermission: Sponsor + */ + sponsorRouter.route("/self").get( + Middleware.Auth.ensureAuthenticated(), + Middleware.Auth.ensureAuthorized(), + + Middleware.Sponsor.findSelf, + Controllers.Sponsor.showSponsor + ); + /** * @api {get} /sponsor/:id get a sponsor's information * @apiName getSponsor diff --git a/tests/sponsor.test.js b/tests/sponsor.test.js index dab90b9d..d87dd584 100644 --- a/tests/sponsor.test.js +++ b/tests/sponsor.test.js @@ -27,8 +27,118 @@ const newT2Sponsor0 = util.sponsor.newT2Sponsor0; let duplicateSponsor = util.sponsor.duplicateAccountLinkSponsor1; +describe("GET user's sponsor info", function () { + it("should fail list a sponsor's information due to authentication from /api/sponsor/self GET", function (done) { + chai.request(server.app) + .get(`/api/sponsor/self`) + // does not have password because of to stripped json + .end(function (err, res) { + res.should.have.status(401); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.AUTH_401_MESSAGE); + + done(); + }); + }); + + it("should FAIL to list a sponsor's info due to authorization /api/sponsor/self GET", function (done) { + util.auth.login(agent, HackerAccount0, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .get(`/api/sponsor/self`) + .end(function (err, res) { + if (err) { + return done(err); + } + res.should.have.status(403); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.AUTH_403_MESSAGE); + res.body.should.have.property("data"); + + done(); + }); + }); + }); + + it("should FAIL to list a sponsor's info due to wrong account type on /api/sponsor/self GET", function (done) { + util.auth.login(agent, Admin0, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .get(`/api/sponsor/self`) + .end(function (err, res) { + if (err) { + return done(err); + } + res.should.have.status(409); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.ACCOUNT_TYPE_409_MESSAGE); + res.body.should.have.property("data"); + + done(); + }); + }); + }); + + it("should FAIL to list a sponsor's info due to lack of sponsor on /api/sponsor/self GET", function (done) { + util.auth.login(agent, newT2SponsorAccount0, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .get(`/api/sponsor/self`) + .end(function (err, res) { + if (err) { + return done(err); + } + res.should.have.status(404); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.SPONSOR_404_MESSAGE); + res.body.should.have.property("data"); + + done(); + }); + }); + }); + + it("should SUCCEED to list user's sponsor info /api/sponsor/self GET", function (done) { + util.auth.login(agent, T1SponsorAccount0, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .get(`/api/sponsor/self`) + .end(function (err, res) { + if (err) { + return done(err); + } + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Success.SPONSOR_READ); + res.body.should.have.property("data"); + res.body.data.should.be.a("object"); + + let sponsor = new Sponsor(T1Sponsor0); + chai.assert.equal(JSON.stringify(res.body.data), JSON.stringify(sponsor.toJSON())); + done(); + }); + }); + }); +}); -describe("GET user sponsor", function () { +describe("GET sponsor by id", function () { it("should fail list a sponsor's information due to authentication from /api/sponsor/:id GET", function (done) { chai.request(server.app) .get(`/api/sponsor/` + T1Sponsor0._id)