diff --git a/constants/routes.constant.js b/constants/routes.constant.js index 224e915c..51c5c582 100644 --- a/constants/routes.constant.js +++ b/constants/routes.constant.js @@ -10,10 +10,6 @@ const authRoutes = { requestType: Constants.REQUEST_TYPES.POST, uri: "/api/auth/logout" }, - "invite": { - requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/auth/invite" - }, "getSelfRoleBindindings": { requestType: Constants.REQUEST_TYPES.GET, uri: "/api/auth/rolebindings/" + Constants.ROLE_CATEGORIES.SELF @@ -181,7 +177,16 @@ const staffRoutes = { "hackerStats": { requestType: Constants.REQUEST_TYPES.GET, uri: "/api/hacker/stats", - } + }, + "postInvite": { + requestType: Constants.REQUEST_TYPES.POST, + uri: "/api/account/invite" + }, + "getInvite": { + requestType: Constants.REQUEST_TYPES.GET, + uri: "/api/account/invite" + }, + } const allRoutes = { diff --git a/constants/success.constant.js b/constants/success.constant.js index bfbc6717..e7d5ae2d 100644 --- a/constants/success.constant.js +++ b/constants/success.constant.js @@ -6,6 +6,7 @@ const ACCOUNT_READ = "Account retrieval successful."; const ACCOUNT_CREATE = "Account creation successful."; const ACCOUNT_UPDATE = "Account update successful."; const ACCOUNT_INVITE = "Account invitation successful."; +const ACCOUNT_GET_INVITES = "Invite retrieval successful."; const AUTH_LOGIN = "Login successful."; const AUTH_LOGOUT = "Logout successful."; @@ -46,8 +47,8 @@ module.exports = { ACCOUNT_CREATE: ACCOUNT_CREATE, ACCOUNT_UPDATE: ACCOUNT_UPDATE, ACCOUNT_INVITE: ACCOUNT_INVITE, + ACCOUNT_GET_INVITES: ACCOUNT_GET_INVITES, ACCOUNT_READ: ACCOUNT_READ, - AUTH_LOGIN: AUTH_LOGIN, AUTH_LOGOUT: AUTH_LOGOUT, AUTH_SEND_RESET_EMAIL: AUTH_SEND_RESET_EMAIL, diff --git a/controllers/account.controller.js b/controllers/account.controller.js index c1c61dfa..740cf072 100644 --- a/controllers/account.controller.js +++ b/controllers/account.controller.js @@ -63,9 +63,18 @@ function invitedAccount(req, res) { }); } +function gotInvites(req, res) { + return res.status(200).json({ + message: Constants.Success.ACCOUNT_GET_INVITES, + data: { + invites: req.body.invites + } + }); +} module.exports = { addUser: addUser, + gotInvites: gotInvites, updatedAccount: updatedAccount, invitedAccount: invitedAccount, showAccount: showAccount, diff --git a/docs/api/api_data.js b/docs/api/api_data.js index ee4a109b..9da4ec8c 100644 --- a/docs/api/api_data.js +++ b/docs/api/api_data.js @@ -205,6 +205,27 @@ define({ "url": "https://api.mchacks.ca/api/account/:id" }] }, + { + "type": "get", + "url": "/account/invite", + "title": "Get all of the invites.", + "name": "getAllInvites", + "group": "Account", + "version": "0.0.8", + "description": "

Get all of the invites that currently exist in the database.

", + "success": { + "examples": [{ + "title": "Success-Response: ", + "content": "{\n \"message\": \"Invite retrieval successful.\", \n \"data\": [{\n \"email\":\"abc@def.com\",\n \"accountType\":\"Hacker\"\n }]\n }", + "type": "object" + }] + }, + "filename": "routes/api/account.js", + "groupTitle": "Account", + "sampleRequest": [{ + "url": "https://api.mchacks.ca/api/account/invite" + }] + }, { "type": "post", "url": "/account/invite", diff --git a/docs/api/api_data.json b/docs/api/api_data.json index 716bc782..0ca98105 100644 --- a/docs/api/api_data.json +++ b/docs/api/api_data.json @@ -204,6 +204,27 @@ "url": "https://api.mchacks.ca/api/account/:id" }] }, + { + "type": "get", + "url": "/account/invite", + "title": "Get all of the invites.", + "name": "getAllInvites", + "group": "Account", + "version": "0.0.8", + "description": "

Get all of the invites that currently exist in the database.

", + "success": { + "examples": [{ + "title": "Success-Response: ", + "content": "{\n \"message\": \"Invite retrieval successful.\", \n \"data\": [{\n \"email\":\"abc@def.com\",\n \"accountType\":\"Hacker\"\n }]\n }", + "type": "object" + }] + }, + "filename": "routes/api/account.js", + "groupTitle": "Account", + "sampleRequest": [{ + "url": "https://api.mchacks.ca/api/account/invite" + }] + }, { "type": "post", "url": "/account/invite", diff --git a/middlewares/account.middleware.js b/middlewares/account.middleware.js index a7f3dd2f..c47d5fb8 100644 --- a/middlewares/account.middleware.js +++ b/middlewares/account.middleware.js @@ -202,12 +202,24 @@ async function inviteAccount(req, res, next) { message: Constants.Error.EMAIL_500_MESSAGE, }); } - +} +/** + * Gets all of the invites in the database and adds it to req.body. + * @param {{}} req + * @param {*} res + * @param {(err?)=>void} next + */ +async function getInvites(req, res, next) { + const invites = await Services.AccountConfirmation.find({}); + req.body.invites = invites; + next(); } module.exports = { parsePatch: parsePatch, parseAccount: parseAccount, + // untested + getInvites: Middleware.Util.asyncMiddleware(getInvites), getByEmail: Middleware.Util.asyncMiddleware(getByEmail), getById: Middleware.Util.asyncMiddleware(getById), // untested diff --git a/routes/api/account.js b/routes/api/account.js index 69862fca..6ae784f4 100644 --- a/routes/api/account.js +++ b/routes/api/account.js @@ -141,6 +141,64 @@ module.exports = { Controllers.Account.addUser ); + /** + * @api {post} /account/invite invites a user to create an account with the specified accountType + * @apiName inviteAccount + * @apiGroup Account + * @apiVersion 0.0.8 + * @apiDescription sends link with token to be used with the account/create route + * + * @apiParam (body) {String} [email] email of the account to be created and where to send the link + * @apiParam (body) {String} [accountType] the type of the account which the user can create, for sponsor this should specify tier as well + * + * @apiSuccess {string} message Success message + * @apiSuccess {object} data Account object + * @apiSuccessExample {object} Success-Response: + * { + "message": "Successfully invited user", + "data": {} + } + * @apiError {string} message Error message + * @apiError {object} data Error object + * @apiErrorExample {object} Error-Response: + * { + "message": "Invalid Authentication", + "data": { + "route": "/invite" + } + } + */ + accountRouter.route("/invite").post( + Middleware.Auth.ensureAuthenticated(), + Middleware.Auth.ensureAuthorized(), + Middleware.Validator.Account.inviteAccountValidator, + Middleware.parseBody.middleware, + Middleware.Account.inviteAccount, + Controllers.Account.invitedAccount + ); + /** + * @api {get} /account/invite Get all of the invites. + * @apiName getAllInvites + * @apiGroup Account + * @apiVersion 0.0.8 + * @apiDescription Get all of the invites that currently exist in the database. + * @apiSuccessExample {object} Success-Response: + * { + "message": "Invite retrieval successful.", + "data": [{ + "email":"abc@def.com", + "accountType":"Hacker" + }] + } + */ + accountRouter.route("/invite").get( + Middleware.Auth.ensureAuthenticated(), + Middleware.Auth.ensureAuthorized(), + Middleware.parseBody.middleware, + Middleware.Account.getInvites, + Controllers.Account.gotInvites + ); + /** * @api {patch} /account/:id update an account's information * @apiName updateOneUser @@ -241,42 +299,6 @@ module.exports = { Controllers.Account.showAccount ); - /** - * @api {post} /account/invite invites a user to create an account with the specified accountType - * @apiName inviteAccount - * @apiGroup Account - * @apiVersion 0.0.8 - * @apiDescription sends link with token to be used with the account/create route - * - * @apiParam (body) {String} [email] email of the account to be created and where to send the link - * @apiParam (body) {String} [accountType] the type of the account which the user can create, for sponsor this should specify tier as well - * - * @apiSuccess {string} message Success message - * @apiSuccess {object} data Account object - * @apiSuccessExample {object} Success-Response: - * { - "message": "Successfully invited user", - "data": {} - } - * @apiError {string} message Error message - * @apiError {object} data Error object - * @apiErrorExample {object} Error-Response: - * { - "message": "Invalid Authentication", - "data": { - "route": "/invite" - } - } - */ - accountRouter.route("/invite").post( - Middleware.Auth.ensureAuthenticated(), - Middleware.Auth.ensureAuthorized(), - Middleware.Validator.Account.inviteAccountValidator, - Middleware.parseBody.middleware, - Middleware.Account.inviteAccount, - Controllers.Account.invitedAccount - ); - apiRouter.use("/account", accountRouter); } }; \ No newline at end of file diff --git a/services/accountConfirmation.service.js b/services/accountConfirmation.service.js index e00fb4cf..c3f1a19c 100644 --- a/services/accountConfirmation.service.js +++ b/services/accountConfirmation.service.js @@ -32,6 +32,17 @@ function findById(id) { return AccountConfirmation.findById(id, logger.queryCallbackFactory(TAG, "AccountConfirmation", "mongoId")); } +/** + * @function find + * @param {*} query the query to search the database by. + * @return {DocumentQuery} The document query will resolve to either account confirmations or null. + * @description Finds an account by query. + */ +function find(query) { + const TAG = `[ AccountConfirmation Service # find ]`; + return AccountConfirmation.find(query, logger.queryCallbackFactory(TAG, "AccountConfirmation", query)); +} + /** * Creates Account Confirmation document in the database * @param {String} type the type of user which to create the token for @@ -158,6 +169,7 @@ function generateAccountInvitationEmail(address, receiverEmail, type, token) { return mailData; } module.exports = { + find: find, findById: findById, findByAccountId: findByAccountId, create: create, diff --git a/tests/account.test.js b/tests/account.test.js index a3f9d5e7..687265b6 100644 --- a/tests/account.test.js +++ b/tests/account.test.js @@ -544,4 +544,55 @@ describe("POST invite account", function () { }); }); }); +}); + +describe("GET invites", function () { + it("Should FAIL to get all invites due to Authentication", function (done) { + chai.request(server.app) + .get("/api/account/invite") + .end(function (err, res) { + res.should.have.status(401); + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.AUTH_401_MESSAGE); + done(); + }); + }); + it("Should FAIL to get all invites due to Authorization", function (done) { + util.auth.login(agent, storedAccount1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .get("/api/account/invite") + .end(function (err, res) { + res.should.have.status(403); + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.AUTH_403_MESSAGE); + done(); + }); + }); + }); + it("Should SUCCEED to get all invites", function (done) { + util.auth.login(agent, Admin1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .get("/api/account/invite") + .end(function (err, res) { + if (err) { + return done(err); + } + res.should.have.status(200); + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Success.ACCOUNT_GET_INVITES); + res.body.should.have.property("data"); + res.body.data.should.have.property("invites"); + res.body.data.invites.length.should.equal(util.accountConfirmation.AccountConfirmationTokens.length); + done(); + }); + }); + }); }); \ No newline at end of file diff --git a/tests/util/accountConfirmation.test.util.js b/tests/util/accountConfirmation.test.util.js index 8b8b682f..949add4c 100644 --- a/tests/util/accountConfirmation.test.util.js +++ b/tests/util/accountConfirmation.test.util.js @@ -26,11 +26,17 @@ const HackerConfirmation2 = { "accountId": Util.Account.NonConfirmedAccount2._id, "accountType": Constants.HACKER, "email": Util.Account.NonConfirmedAccount2.email -} +}; const HackerConfirmation3 = { "_id": mongoose.Types.ObjectId(), - "email": Util.Account.newAccount1 + "email": Util.Account.newAccount1.email +}; + +const HackerConfirmation4 = { + "_id": mongoose.Types.ObjectId(), + "accountType": Constants.HACKER, + "email": "abcd@efgh.com" }; // Using a real ID which is stored but corresponds to another account @@ -46,7 +52,8 @@ const FakeToken = Services.AccountConfirmation.generateToken(FakeHackerToken._id const AccountConfirmationTokens = [ HackerConfirmation, HackerConfirmation2, - HackerConfirmation3 + HackerConfirmation3, + HackerConfirmation4 ]; function storeAll(attributes) {