From 75ef99d2e3cc8d30531b45be0397fdc29aa74a0e Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Sat, 29 Dec 2018 18:46:20 -0500 Subject: [PATCH 01/13] change to enum validation --- middlewares/validators/account.validator.js | 7 +- middlewares/validators/hacker.validator.js | 5 +- middlewares/validators/validator.helper.js | 71 --------------------- 3 files changed, 7 insertions(+), 76 deletions(-) diff --git a/middlewares/validators/account.validator.js b/middlewares/validators/account.validator.js index aa788dfc..b12bbcdc 100644 --- a/middlewares/validators/account.validator.js +++ b/middlewares/validators/account.validator.js @@ -1,5 +1,6 @@ "use strict"; const VALIDATOR = require("./validator.helper"); +const Constants = require("../../constants/general.constant"); module.exports = { newAccountValidator: [ @@ -8,7 +9,7 @@ module.exports = { VALIDATOR.pronounValidator("body", "pronoun", false), VALIDATOR.emailValidator("body", "email", false), VALIDATOR.alphaArrayValidator("body", "dietaryRestrictions", false), - VALIDATOR.shirtSizeValidator("body", "shirtSize", false), + VALIDATOR.enumValidator("body", "shirtSize", Constants.SHIRT_SIZES, false), VALIDATOR.passwordValidator("body", "password", false), VALIDATOR.jwtValidator("param", "token", process.env.JWT_CONFIRM_ACC_SECRET, true), VALIDATOR.dateValidator("body", "birthDate", false), @@ -20,12 +21,12 @@ module.exports = { VALIDATOR.pronounValidator("body", "pronoun", true), VALIDATOR.emailValidator("body", "email", true), VALIDATOR.alphaArrayValidator("body", "dietaryRestrictions", true), - VALIDATOR.shirtSizeValidator("body", "shirtSize", true), + VALIDATOR.enumValidator("body", "shirtSize", Constants.SHIRT_SIZES, true), VALIDATOR.dateValidator("body", "birthDate", true), VALIDATOR.phoneNumberValidator("body", "phoneNumber", true) ], inviteAccountValidator: [ VALIDATOR.emailValidator("body", "email", false), - VALIDATOR.accountTypeValidator("body", "accountType", false) + VALIDATOR.enumValidator("body", "accountType", Constants.EXTENDED_USER_TYPES, false) ] }; \ No newline at end of file diff --git a/middlewares/validators/hacker.validator.js b/middlewares/validators/hacker.validator.js index bf90c54f..56c4aafd 100644 --- a/middlewares/validators/hacker.validator.js +++ b/middlewares/validators/hacker.validator.js @@ -1,5 +1,6 @@ "use strict"; const VALIDATOR = require("./validator.helper"); +const Constants = require("../../constants/general.constant"); module.exports = { newHackerValidator: [ @@ -29,10 +30,10 @@ module.exports = { VALIDATOR.booleanValidator("body", "needsBus", true) ], updateStatusValidator: [ - VALIDATOR.hackerStatusValidator("body", "status", false) + VALIDATOR.enumValidator("body", "status", Constants.HACKER_STATUSES, false), ], checkInStatusValidator: [ - VALIDATOR.hackerCheckInStatusValidator("body", "status", false) + VALIDATOR.enumValidator("body", "status", Constants.HACKER_STATUS_CHECKED_IN, false) ], uploadResumeValidator: [ VALIDATOR.mongoIdValidator("param", "id", false) diff --git a/middlewares/validators/validator.helper.js b/middlewares/validators/validator.helper.js index 86fd6d84..997671c2 100644 --- a/middlewares/validators/validator.helper.js +++ b/middlewares/validators/validator.helper.js @@ -256,25 +256,6 @@ function alphaArrayValidationHelper(value) { return true; } -/** - * Validates that field must be one of the shirt size enums. - * @param {"query" | "body" | "header" | "param"} fieldLocation the location where the field should be found - * @param {string} fieldname name of the field that needs to be validated. - * @param {boolean} optional whether the field is optional or not. - */ -function shirtSizeValidator(fieldLocation, fieldname, optional = true) { - const size = setProperValidationChainBuilder(fieldLocation, fieldname, "invalid shirt size"); - const shirtSizes = ["XS", "S", "M", "L", "XL", "XXL"]; - - if (optional) { - return size.optional({ - checkFalsy: true - }).isIn(shirtSizes).withMessage(`Must be one of ${shirtSizes.join(",")}`); - } else { - return size.exists().withMessage("shirt size must exist").isIn(shirtSizes).withMessage(`must be one of ${shirtSizes.join(",")}`); - } -} - /** * Validates that field must be at least 6 characters long. * TODO: impose better restrictions. @@ -297,35 +278,6 @@ function passwordValidator(fieldLocation, fieldname, optional = true) { } } -/** - * Validates that field must be one of the status enums. - * @param {"query" | "body" | "header" | "param"} fieldLocation the location where the field should be found - * @param {string} fieldname name of the field that needs to be validated. - * @param {boolean} optional whether the field is optional or not. - */ -function hackerStatusValidator(fieldLocation, fieldname, optional = true) { - const status = setProperValidationChainBuilder(fieldLocation, fieldname, "invalid status"); - - if (optional) { - return status.optional({ - checkFalsy: true - }).isIn(Constants.HACKER_STATUSES).withMessage(`Status must be in ${Constants.HACKER_STATUSES}`); - } else { - return status.exists().withMessage(`Status must be in ${Constants.HACKER_STATUSES}`); - } -} - -function hackerCheckInStatusValidator(fieldLocation, fieldname, optional = true) { - const status = setProperValidationChainBuilder(fieldLocation, fieldname, "invalid status"); - - if (optional) { - return status.optional({ - checkFalsy: true - }).isIn(Constants.HACKER_STATUS_CHECKED_IN).withMessage(`Status must be ${Constants.HACKER_STATUS_CHECKED_IN}`); - } else { - return status.exists().withMessage(`Status must be ${Constants.HACKER_STATUS_CHECKED_IN}`); - } -} /** * Validates that field must be a valid application. @@ -588,25 +540,6 @@ function phoneNumberValidator(fieldLocation, fieldname, optional = true) { } } -/** - * Validates that field must be a valid account type - * @param {"query" | "body" | "header" | "param"} fieldLocation the location where the field should be found - * @param {string} fieldname name of the field that needs to be validated. - * @param {boolean} optional whether the field is optional or not. - */ -function accountTypeValidator(fieldLocation, fieldname, optional = true) { - const accountType = setProperValidationChainBuilder(fieldLocation, fieldname, "Invalid account type"); - if (optional) { - return accountType.optional({ - checkFalsy: true - }).isIn(Constants.EXTENDED_USER_TYPES); - } else { - return accountType.exists() - .withMessage("Account type must be provided") - .isIn(Constants.EXTENDED_USER_TYPES); - } -} - /** * Validates that field must be an array of routes * @param {"query" | "body" | "header" | "param"} fieldLocation the location where the field should be found @@ -731,9 +664,7 @@ module.exports = { emailValidator: emailValidator, alphaValidator: alphaValidator, alphaArrayValidator: alphaArrayValidator, - shirtSizeValidator: shirtSizeValidator, passwordValidator: passwordValidator, - hackerStatusValidator: hackerStatusValidator, booleanValidator: booleanValidator, applicationValidator: applicationValidator, jwtValidator: jwtValidator, @@ -743,8 +674,6 @@ module.exports = { searchSortValidator: searchSortValidator, phoneNumberValidator: phoneNumberValidator, dateValidator: dateValidator, - hackerCheckInStatusValidator: hackerCheckInStatusValidator, - accountTypeValidator: accountTypeValidator, enumValidator: enumValidator, routesValidator: routesValidator, }; \ No newline at end of file From b3bca6e6a83af4961b48f60a049ea7ee5603ef46 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Tue, 1 Jan 2019 15:35:30 -0500 Subject: [PATCH 02/13] Add authentication to team create --- middlewares/validators/team.validator.js | 2 -- routes/api/team.js | 12 +++++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/middlewares/validators/team.validator.js b/middlewares/validators/team.validator.js index f6929d13..ae93803d 100644 --- a/middlewares/validators/team.validator.js +++ b/middlewares/validators/team.validator.js @@ -4,8 +4,6 @@ const VALIDATOR = require("./validator.helper"); module.exports = { newTeamValidator: [ VALIDATOR.nameValidator("body", "name", false), - // members by mongoID if the team creator is able to provide - VALIDATOR.mongoIdArrayValidator("body", "members", true), VALIDATOR.devpostValidator("body", "devpostURL", true), VALIDATOR.nameValidator("body", "projectName", false) ], diff --git a/routes/api/team.js b/routes/api/team.js index d6dfdf36..b0afcb56 100644 --- a/routes/api/team.js +++ b/routes/api/team.js @@ -13,7 +13,8 @@ const Middleware = { }, /* Insert all of ther middleware require statements here */ parseBody: require("../../middlewares/parse-body.middleware"), - Team: require("../../middlewares/team.middleware") + Team: require("../../middlewares/team.middleware"), + Auth: require("../../middlewares/auth.middleware") }; module.exports = { @@ -21,13 +22,12 @@ module.exports = { const teamRouter = new express.Router(); /** - * @api {post} /team/ create a new team + * @api {post} /team/ create a new team consisting of only the logged in user * @apiName createTeam * @apiGroup Team * @apiVersion 0.0.8 * * @apiParam (body) {String} name Name of the team. - * @apiParam (body) {MongoID[]} [members] Array of members in team. * @apiParam (body) {String} [devpostURL] Devpost link to hack. Once the link is sent, the hack will be considered to be submitted. * @apiParam (body) {String} projectName Name of the team. * @@ -45,16 +45,14 @@ module.exports = { * {"message": "Error while creating team", "data": {}} */ teamRouter.route("/").post( + Middleware.Auth.ensureAuthenticated(), + Middleware.Auth.ensureAuthorized(), // Validators Middleware.Validator.Team.newTeamValidator, - Middleware.parseBody.middleware, Middleware.Team.parseTeam, - // check that member is not already in a team - Middleware.Team.ensureUniqueHackerId, - Middleware.Team.createTeam, Controllers.Team.createdTeam ); From 0a16bf34fdfd8d98cabb7e03630e8461e0600508 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Tue, 1 Jan 2019 16:14:04 -0500 Subject: [PATCH 03/13] Create team --- constants/role.constant.js | 1 + middlewares/team.middleware.js | 49 +++++++++++++++++++++++++++++++--- routes/api/team.js | 3 +-- tests/team.test.js | 38 ++++++++++++++++++++------ tests/util/team.test.util.js | 6 +++++ 5 files changed, 84 insertions(+), 13 deletions(-) diff --git a/constants/role.constant.js b/constants/role.constant.js index bee2a6f2..1a45e4d2 100644 --- a/constants/role.constant.js +++ b/constants/role.constant.js @@ -41,6 +41,7 @@ const hackerRole = { Constants.Routes.hackerRoutes.getSelf, Constants.Routes.teamRoutes.join, + Constants.Routes.teamRoutes.post, ] }; diff --git a/middlewares/team.middleware.js b/middlewares/team.middleware.js index 73161b9d..2102c0d4 100644 --- a/middlewares/team.middleware.js +++ b/middlewares/team.middleware.js @@ -69,10 +69,10 @@ async function createTeam(req, res, next) { message: Constants.Error.TEAM_CREATE_500_MESSAGE, data: {} }); - } else { - req.body.team = team; - return next(); } + + req.body.team = team; + return next(); } /** @@ -214,6 +214,47 @@ function parseTeam(req, res, next) { return next(); } +async function parseNewTeam(req, res, next) { + const teamDetails = { + _id: mongoose.Types.ObjectId(), + name: req.body.name, + members: [], + devpostURL: req.body.devpostURL, + projectName: req.body.projectName + }; + + delete req.body.name; + delete req.body.members; + delete req.body.devpostURL; + delete req.body.projectName; + + // hacker should exist because of authorization + const hacker = await Services.Hacker.findByAccountId(req.user.id); + + if (!hacker) { + return next({ + status: 404, + message: Constants.Error.HACKER_404_MESSAGE, + data: { + id: req.user.id + } + }); + } + + // hacker should not be in another team + if (hacker.teamId !== undefined) { + return next({ + status: 409, + message: Constants.Error.TEAM_MEMBER_409_MESSAGE, + }); + } + + teamDetails.members.push(hacker._id); + + req.body.teamDetails = teamDetails; + return next(); +} + module.exports = { parseTeam: parseTeam, findById: Util.asyncMiddleware(findById), @@ -221,4 +262,6 @@ module.exports = { ensureUniqueHackerId: Util.asyncMiddleware(ensureUniqueHackerId), ensureSpace: Util.asyncMiddleware(ensureSpace), updateHackerTeam: Util.asyncMiddleware(updateHackerTeam), + parseNewTeam: Util.asyncMiddleware(parseNewTeam), + }; \ No newline at end of file diff --git a/routes/api/team.js b/routes/api/team.js index 407efa83..4aaf52ca 100644 --- a/routes/api/team.js +++ b/routes/api/team.js @@ -50,8 +50,7 @@ module.exports = { // Validators Middleware.Validator.Team.newTeamValidator, Middleware.parseBody.middleware, - - Middleware.Team.parseTeam, + Middleware.Team.parseNewTeam, Middleware.Team.createTeam, Controllers.Team.createdTeam diff --git a/tests/team.test.js b/tests/team.test.js index c5744802..daf7c4e7 100644 --- a/tests/team.test.js +++ b/tests/team.test.js @@ -39,26 +39,48 @@ describe("GET team", function () { }); describe("POST create team", function () { - it("should SUCCEED and create a new team", function (done) { + it("should FAIL to create a new team due to lack of authentication", function (done) { chai.request(server.app) .post(`/api/team/`) .type("application/json") .send(util.team.newTeam1) .end(function (err, res) { - res.should.have.status(200); + res.should.have.status(401); res.should.be.json; res.body.should.have.property("message"); - res.body.message.should.equal(Constants.Success.TEAM_CREATE); + res.body.message.should.equal(Constants.Error.AUTH_401_MESSAGE); res.body.should.have.property("data"); - // deleting _id because that was generated, and not part of original data - const team = (new Team(util.team.newTeam1)).toJSON(); - delete res.body.data.id; - delete team.id; - chai.assert.equal(JSON.stringify(res.body.data), JSON.stringify(team)); done(); }); }); + + it("should SUCCEED and create a new team", function (done) { + util.auth.login(agent, util.account.Account2, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .post(`/api/team/`) + .type("application/json") + .send(util.team.newTeam1) + .end(function (err, res) { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Success.TEAM_CREATE); + res.body.should.have.property("data"); + + // deleting _id because that was generated, and not part of original data + const team = (new Team(util.team.createdNewTeam1)).toJSON(); + delete res.body.data.id; + delete team.id; + chai.assert.equal(JSON.stringify(res.body.data), JSON.stringify(team)); + done(); + }); + }); + }); }); describe("PATCH change team", function () { diff --git a/tests/util/team.test.util.js b/tests/util/team.test.util.js index abbe81ea..1eed262a 100644 --- a/tests/util/team.test.util.js +++ b/tests/util/team.test.util.js @@ -7,6 +7,11 @@ const mongoose = require("mongoose"); const logger = require("../../services/logger.service"); const newTeam1 = { + "name": "BronzeTeam", + "projectName": "YetAnotherProject" +}; + +const createdNewTeam1 = { "name": "BronzeTeam", "members": [Util.Hacker.HackerB._id], "projectName": "YetAnotherProject" @@ -65,6 +70,7 @@ async function dropAll() { module.exports = { newTeam1: newTeam1, + createdNewTeam1: createdNewTeam1, Team1: Team1, Team2: Team2, Team3: Team3, From 29b56e1557ffa533aa236b66bac5380a2f40906a Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Tue, 1 Jan 2019 16:36:06 -0500 Subject: [PATCH 04/13] Add tests for team --- middlewares/team.middleware.js | 2 ++ services/team.service.js | 3 +- tests/team.test.js | 63 ++++++++++++++++++++++++++++++++++ tests/util/team.test.util.js | 10 ++++-- 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/middlewares/team.middleware.js b/middlewares/team.middleware.js index 2102c0d4..20e06044 100644 --- a/middlewares/team.middleware.js +++ b/middlewares/team.middleware.js @@ -62,6 +62,8 @@ async function ensureUniqueHackerId(req, res, next) { async function createTeam(req, res, next) { const teamDetails = req.body.teamDetails; + const prevTeam = await Services.Team.findByName(teamDetails.name); + const team = await Services.Team.createTeam(teamDetails); if (!team) { diff --git a/services/team.service.js b/services/team.service.js index 4eb29168..157ccf29 100644 --- a/services/team.service.js +++ b/services/team.service.js @@ -35,7 +35,8 @@ function createTeam(teamDetails) { const team = new Team(teamDetails); - return team.save(); + // return team.save(); + return Team.create(teamDetails); } /** diff --git a/tests/team.test.js b/tests/team.test.js index daf7c4e7..5eb14e70 100644 --- a/tests/team.test.js +++ b/tests/team.test.js @@ -55,6 +55,69 @@ describe("POST create team", function () { }); }); + it("should FAIL to create a new team due to lack of authorization", function (done) { + util.auth.login(agent, util.account.Account3, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .post(`/api/team/`) + .type("application/json") + .send(util.team.newTeam1) + .end(function (err, res) { + 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 create a new team due to logged in user not being a hacker", function (done) { + util.auth.login(agent, util.account.Admin1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .post(`/api/team/`) + .type("application/json") + .send(util.team.newTeam1) + .end(function (err, res) { + res.should.have.status(404); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.HACKER_404_MESSAGE); + res.body.should.have.property("data"); + + done(); + }); + }); + }); + + it("should FAIL to create a new team due to duplicate team name", function (done) { + util.auth.login(agent, util.account.Account2, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .post(`/api/team/`) + .type("application/json") + .send(util.team.duplicateTeamName1) + .end(function (err, res) { + res.should.have.status(422); + res.should.be.json; + + done(); + }); + }); + }); + it("should SUCCEED and create a new team", function (done) { util.auth.login(agent, util.account.Account2, (error) => { if (error) { diff --git a/tests/util/team.test.util.js b/tests/util/team.test.util.js index 1eed262a..5ad4b52b 100644 --- a/tests/util/team.test.util.js +++ b/tests/util/team.test.util.js @@ -6,13 +6,18 @@ const Team = require("../../models/team.model"); const mongoose = require("mongoose"); const logger = require("../../services/logger.service"); +const duplicateTeamName1 = { + "name": "SilverTeam", + "projectName": "AProject" +}; + const newTeam1 = { - "name": "BronzeTeam", + "name": "BronzeTeam1", "projectName": "YetAnotherProject" }; const createdNewTeam1 = { - "name": "BronzeTeam", + "name": "BronzeTeam1", "members": [Util.Hacker.HackerB._id], "projectName": "YetAnotherProject" }; @@ -71,6 +76,7 @@ async function dropAll() { module.exports = { newTeam1: newTeam1, createdNewTeam1: createdNewTeam1, + duplicateTeamName1: duplicateTeamName1, Team1: Team1, Team2: Team2, Team3: Team3, From 6d91a6f6bd6dc9ef9d12af7e3d41608d2c14130d Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Thu, 3 Jan 2019 09:03:23 -0500 Subject: [PATCH 05/13] WIP team post duplication issue --- middlewares/team.middleware.js | 10 +- models/team.model.js | 7 +- services/team.service.js | 6 +- tests/team.test.js | 256 ++++++++++++++++----------------- tests/util/team.test.util.js | 6 +- 5 files changed, 151 insertions(+), 134 deletions(-) diff --git a/middlewares/team.middleware.js b/middlewares/team.middleware.js index 20e06044..4a5c1f1b 100644 --- a/middlewares/team.middleware.js +++ b/middlewares/team.middleware.js @@ -73,6 +73,14 @@ async function createTeam(req, res, next) { }); } + // const new_team = new Team(teamDetails); + + // await new_team.save(); + + // const teams = await Team.find({ + // name: teamDetails.name + // }); + req.body.team = team; return next(); } @@ -218,7 +226,7 @@ function parseTeam(req, res, next) { async function parseNewTeam(req, res, next) { const teamDetails = { - _id: mongoose.Types.ObjectId(), + // _id: mongoose.Types.ObjectId(), name: req.body.name, members: [], devpostURL: req.body.devpostURL, diff --git a/models/team.model.js b/models/team.model.js index cd69ced9..3696768b 100644 --- a/models/team.model.js +++ b/models/team.model.js @@ -6,8 +6,9 @@ const Constants = require("../constants/general.constant"); const TeamSchema = new mongoose.Schema({ name: { type: String, + required: true, unique: true, - required: true + index: true, }, members: { type: [{ @@ -23,6 +24,10 @@ const TeamSchema = new mongoose.Schema({ projectName: String }); +TeamSchema.index({ + name: 1 +}); + function validateTeamSize(membersArr) { return membersArr.length <= Constants.MAX_TEAM_SIZE; } diff --git a/services/team.service.js b/services/team.service.js index 157ccf29..29d7f1af 100644 --- a/services/team.service.js +++ b/services/team.service.js @@ -30,11 +30,15 @@ function findTeamByHackerId(hackerId) { * @return {Promise} The promise will resolve to a team object if save was successful. * @description Adds a new team to database. */ -function createTeam(teamDetails) { +async function createTeam(teamDetails) { const TAG = `[Team Service # createTeam]:`; const team = new Team(teamDetails); + await Team.init(); + + delete teamDetails._id; + // return team.save(); return Team.create(teamDetails); } diff --git a/tests/team.test.js b/tests/team.test.js index 5eb14e70..c237378f 100644 --- a/tests/team.test.js +++ b/tests/team.test.js @@ -146,142 +146,142 @@ describe("POST create team", function () { }); }); -describe("PATCH change team", function () { - it("should FAIL to join a hacker to a team due to lack of authentication", function (done) { - chai.request(server.app) - .patch(`/api/team/join/`) - .type("application/json") - .send({ - teamName: "BronzeTeam", - }) - .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); - res.body.should.have.property("data"); +// describe("PATCH change team", function () { +// it("should FAIL to join a hacker to a team due to lack of authentication", function (done) { +// chai.request(server.app) +// .patch(`/api/team/join/`) +// .type("application/json") +// .send({ +// teamName: "BronzeTeam", +// }) +// .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); +// res.body.should.have.property("data"); - done(); - }); - }); +// done(); +// }); +// }); - it("should FAIL to join a volunteer to a team.", function (done) { - util.auth.login(agent, util.account.Account5, (error) => { - if (error) { - agent.close(); - return done(error); - } - return agent - .patch(`/api/team/join/`) - .type("application/json") - .send({ - teamName: "BronzeTeam", - }) - .end(function (err, res) { - 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"); +// it("should FAIL to join a volunteer to a team.", function (done) { +// util.auth.login(agent, util.account.Account5, (error) => { +// if (error) { +// agent.close(); +// return done(error); +// } +// return agent +// .patch(`/api/team/join/`) +// .type("application/json") +// .send({ +// teamName: "BronzeTeam", +// }) +// .end(function (err, res) { +// 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(); - }); - }); - }); +// done(); +// }); +// }); +// }); - it("should FAIL to join a hacker to a team that doesn't exist.", function (done) { - util.auth.login(agent, util.account.Account1, (error) => { - if (error) { - agent.close(); - return done(error); - } - return agent - .patch(`/api/team/join/`) - .type("application/json") - .send({ - teamName: "NonExistTeam", - }) - .end(function (err, res) { - res.should.have.status(404); - res.should.be.json; - res.body.should.have.property("message"); - res.body.message.should.equal(Constants.Error.TEAM_404_MESSAGE); - res.body.should.have.property("data"); +// it("should FAIL to join a hacker to a team that doesn't exist.", function (done) { +// util.auth.login(agent, util.account.Account1, (error) => { +// if (error) { +// agent.close(); +// return done(error); +// } +// return agent +// .patch(`/api/team/join/`) +// .type("application/json") +// .send({ +// teamName: "NonExistTeam", +// }) +// .end(function (err, res) { +// res.should.have.status(404); +// res.should.be.json; +// res.body.should.have.property("message"); +// res.body.message.should.equal(Constants.Error.TEAM_404_MESSAGE); +// res.body.should.have.property("data"); - done(); - }); - }); - }); +// done(); +// }); +// }); +// }); - it("should FAIL to join a hacker to a team that is full.", function (done) { - util.auth.login(agent, util.account.Account1, (error) => { - if (error) { - agent.close(); - return done(error); - } - return agent - .patch(`/api/team/join/`) - .type("application/json") - .send({ - teamName: "FullTeam", - }) - .end(function (err, res) { - res.should.have.status(422); - res.should.be.json; - res.body.should.have.property("message"); - res.body.message.should.equal(Constants.Error.TEAM_SIZE_422_MESSAGE); - res.body.should.have.property("data"); +// it("should FAIL to join a hacker to a team that is full.", function (done) { +// util.auth.login(agent, util.account.Account1, (error) => { +// if (error) { +// agent.close(); +// return done(error); +// } +// return agent +// .patch(`/api/team/join/`) +// .type("application/json") +// .send({ +// teamName: "FullTeam", +// }) +// .end(function (err, res) { +// res.should.have.status(422); +// res.should.be.json; +// res.body.should.have.property("message"); +// res.body.message.should.equal(Constants.Error.TEAM_SIZE_422_MESSAGE); +// res.body.should.have.property("data"); - done(); - }); - }); - }); +// done(); +// }); +// }); +// }); - it("should SUCCEED and join a hacker without a team to a team.", function (done) { - util.auth.login(agent, util.account.Account2, (error) => { - if (error) { - agent.close(); - return done(error); - } - return agent - .patch(`/api/team/join/`) - .type("application/json") - .send({ - teamName: "BronzeTeam", - }) - .end(function (err, res) { - res.should.have.status(200); - res.should.be.json; - res.body.should.have.property("message"); - res.body.message.should.equal(Constants.Success.TEAM_JOIN); - res.body.should.have.property("data"); +// it("should SUCCEED and join a hacker without a team to a team.", function (done) { +// util.auth.login(agent, util.account.Account2, (error) => { +// if (error) { +// agent.close(); +// return done(error); +// } +// return agent +// .patch(`/api/team/join/`) +// .type("application/json") +// .send({ +// teamName: "BronzeTeam", +// }) +// .end(function (err, res) { +// res.should.have.status(200); +// res.should.be.json; +// res.body.should.have.property("message"); +// res.body.message.should.equal(Constants.Success.TEAM_JOIN); +// res.body.should.have.property("data"); - done(); - }); - }); - }); +// done(); +// }); +// }); +// }); - it("should SUCCEED and join a hacker on a team to aother team.", function (done) { - util.auth.login(agent, util.account.Account1, (error) => { - if (error) { - agent.close(); - return done(error); - } - return agent - .patch(`/api/team/join/`) - .type("application/json") - .send({ - teamName: "SilverTeam", - }) - .end(function (err, res) { - res.should.have.status(200); - res.should.be.json; - res.body.should.have.property("message"); - res.body.message.should.equal(Constants.Success.TEAM_JOIN); - res.body.should.have.property("data"); +// it("should SUCCEED and join a hacker on a team to aother team.", function (done) { +// util.auth.login(agent, util.account.Account1, (error) => { +// if (error) { +// agent.close(); +// return done(error); +// } +// return agent +// .patch(`/api/team/join/`) +// .type("application/json") +// .send({ +// teamName: "SilverTeam", +// }) +// .end(function (err, res) { +// res.should.have.status(200); +// res.should.be.json; +// res.body.should.have.property("message"); +// res.body.message.should.equal(Constants.Success.TEAM_JOIN); +// res.body.should.have.property("data"); - done(); - }); - }); - }); -}); \ No newline at end of file +// done(); +// }); +// }); +// }); +// }); \ No newline at end of file diff --git a/tests/util/team.test.util.js b/tests/util/team.test.util.js index 5ad4b52b..5ad7b8ac 100644 --- a/tests/util/team.test.util.js +++ b/tests/util/team.test.util.js @@ -23,7 +23,7 @@ const createdNewTeam1 = { }; const Team1 = { - "_id": mongoose.Types.ObjectId(), + // "_id": mongoose.Types.ObjectId(), "name": "BronzeTeam", "members": [Util.Hacker.HackerA._id], "devpostURL": "justanother.devpost.com", @@ -31,7 +31,7 @@ const Team1 = { }; const Team2 = { - "_id": mongoose.Types.ObjectId(), + // "_id": mongoose.Types.ObjectId(), "name": "SilverTeam", "members": [Util.Hacker.HackerC._id], "devpostURL": "watwatwat.devpost.com", @@ -39,7 +39,7 @@ const Team2 = { }; const Team3 = { - "_id": mongoose.Types.ObjectId(), + // "_id": mongoose.Types.ObjectId(), "name": "FullTeam", "members": [Util.Hacker.HackerD._id, Util.Hacker.HackerE._id, Util.Hacker.HackerF._id, Util.Hacker.HackerG._id] }; From b03d35a390a20b31cfd4f8aefafddf6d1f0b8703 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Fri, 4 Jan 2019 20:00:33 -0500 Subject: [PATCH 06/13] Add check for duplicate team name, and test for hacker already being in a team --- constants/error.constant.js | 2 ++ middlewares/team.middleware.js | 38 +++++++++++++++++++++++----------- models/team.model.js | 2 -- routes/api/team.js | 2 ++ tests/team.test.js | 27 +++++++++++++++++++++++- tests/util/hacker.test.util.js | 1 + tests/util/team.test.util.js | 6 +++--- 7 files changed, 60 insertions(+), 18 deletions(-) diff --git a/constants/error.constant.js b/constants/error.constant.js index 3e9879e0..94ad88ae 100644 --- a/constants/error.constant.js +++ b/constants/error.constant.js @@ -11,6 +11,7 @@ const SPONSOR_ID_409_MESSAGE = "Conflict with sponsor accountId link"; const VOLUNTEER_ID_409_MESSAGE = "Conflict with volunteer accountId link"; const HACKER_ID_409_MESSAGE = "Conflict with hacker accountId link"; const TEAM_MEMBER_409_MESSAGE = "Conflict with team member being in another team"; +const TEAM_NAME_409_MESSAGE = "Conflict with team name already in use"; const HACKER_STATUS_409_MESSAGE = "Conflict with hacker status"; const TEAM_MEMBER_422_MESSAGE = "Duplicate team member in input"; @@ -69,4 +70,5 @@ module.exports = { TEAM_SIZE_422_MESSAGE: TEAM_SIZE_422_MESSAGE, ROLE_DUPLICATE_422_MESSAGE: ROLE_DUPLICATE_422_MESSAGE, ROLE_CREATE_500_MESSAGE: ROLE_CREATE_500_MESSAGE, + TEAM_NAME_409_MESSAGE: TEAM_NAME_409_MESSAGE, }; \ No newline at end of file diff --git a/middlewares/team.middleware.js b/middlewares/team.middleware.js index 4a5c1f1b..16cfdafb 100644 --- a/middlewares/team.middleware.js +++ b/middlewares/team.middleware.js @@ -62,8 +62,6 @@ async function ensureUniqueHackerId(req, res, next) { async function createTeam(req, res, next) { const teamDetails = req.body.teamDetails; - const prevTeam = await Services.Team.findByName(teamDetails.name); - const team = await Services.Team.createTeam(teamDetails); if (!team) { @@ -73,20 +71,12 @@ async function createTeam(req, res, next) { }); } - // const new_team = new Team(teamDetails); - - // await new_team.save(); - - // const teams = await Team.find({ - // name: teamDetails.name - // }); - req.body.team = team; return next(); } /** - * @function ensureSpance + * @function ensureSpace * @param {{body: {teamName: string}}} req * @param {JSON} res * @param {(err?)=>void} next @@ -113,6 +103,30 @@ async function ensureSpace(req, res, next) { return next(); } +/** + * @function ensureFreeTeamName + * @param {{body: {teamName: string}}} req + * @param {JSON} res + * @param {(err?)=>void} next + * @return {void} + * @description Checks to see that the team name is not in use. + */ +async function ensureFreeTeamName(req, res, next) { + const teamDetails = req.body.teamDetails; + + const team = await Services.Team.findByName(teamDetails.name); + + if (team) { + return next({ + status: 409, + message: Constants.Error.TEAM_NAME_409_MESSAGE, + data: teamDetails.name + }); + } + + return next(); +} + /** * @async * @function findById @@ -273,5 +287,5 @@ module.exports = { ensureSpace: Util.asyncMiddleware(ensureSpace), updateHackerTeam: Util.asyncMiddleware(updateHackerTeam), parseNewTeam: Util.asyncMiddleware(parseNewTeam), - + ensureFreeTeamName: Util.asyncMiddleware(ensureFreeTeamName), }; \ No newline at end of file diff --git a/models/team.model.js b/models/team.model.js index 3696768b..dfbc1749 100644 --- a/models/team.model.js +++ b/models/team.model.js @@ -7,8 +7,6 @@ const TeamSchema = new mongoose.Schema({ name: { type: String, required: true, - unique: true, - index: true, }, members: { type: [{ diff --git a/routes/api/team.js b/routes/api/team.js index 4aaf52ca..12726999 100644 --- a/routes/api/team.js +++ b/routes/api/team.js @@ -52,6 +52,8 @@ module.exports = { Middleware.parseBody.middleware, Middleware.Team.parseNewTeam, + Middleware.Team.ensureFreeTeamName, + Middleware.Team.createTeam, Controllers.Team.createdTeam ); diff --git a/tests/team.test.js b/tests/team.test.js index c237378f..7288d324 100644 --- a/tests/team.test.js +++ b/tests/team.test.js @@ -110,9 +110,34 @@ describe("POST create team", function () { .type("application/json") .send(util.team.duplicateTeamName1) .end(function (err, res) { - res.should.have.status(422); + res.should.have.status(409); res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.TEAM_NAME_409_MESSAGE); + res.body.should.have.property("data"); + res.body.data.should.equal(util.team.duplicateTeamName1.name); + + done(); + }); + }); + }); + it("should Fail to create a new team due to hacker already being in a team", function (done) { + util.auth.login(agent, util.account.Account1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .post(`/api/team/`) + .type("application/json") + .send(util.team.newTeam1) + .end(function (err, res) { + res.should.have.status(409); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.TEAM_MEMBER_409_MESSAGE); + res.body.should.have.property("data"); done(); }); }); diff --git a/tests/util/hacker.test.util.js b/tests/util/hacker.test.util.js index 457c1f11..ae8bea84 100644 --- a/tests/util/hacker.test.util.js +++ b/tests/util/hacker.test.util.js @@ -155,6 +155,7 @@ const HackerA = { "major": "EE", "graduationYear": 2019, "codeOfConduct": true, + "teamId": mongoose.Types.ObjectId.createFromTime(101), }; const HackerB = { "_id": mongoose.Types.ObjectId(), diff --git a/tests/util/team.test.util.js b/tests/util/team.test.util.js index 5ad7b8ac..e39ae069 100644 --- a/tests/util/team.test.util.js +++ b/tests/util/team.test.util.js @@ -23,7 +23,7 @@ const createdNewTeam1 = { }; const Team1 = { - // "_id": mongoose.Types.ObjectId(), + "_id": mongoose.Types.ObjectId.createFromTime(101), "name": "BronzeTeam", "members": [Util.Hacker.HackerA._id], "devpostURL": "justanother.devpost.com", @@ -31,7 +31,7 @@ const Team1 = { }; const Team2 = { - // "_id": mongoose.Types.ObjectId(), + "_id": mongoose.Types.ObjectId(), "name": "SilverTeam", "members": [Util.Hacker.HackerC._id], "devpostURL": "watwatwat.devpost.com", @@ -39,7 +39,7 @@ const Team2 = { }; const Team3 = { - // "_id": mongoose.Types.ObjectId(), + "_id": mongoose.Types.ObjectId(), "name": "FullTeam", "members": [Util.Hacker.HackerD._id, Util.Hacker.HackerE._id, Util.Hacker.HackerF._id, Util.Hacker.HackerG._id] }; From ac64557c01035098de969c46d6d2f8bb28009c31 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Fri, 4 Jan 2019 20:01:14 -0500 Subject: [PATCH 07/13] uncomment tests --- tests/team.test.js | 256 ++++++++++++++++++++++----------------------- 1 file changed, 128 insertions(+), 128 deletions(-) diff --git a/tests/team.test.js b/tests/team.test.js index 7288d324..c76d8ec2 100644 --- a/tests/team.test.js +++ b/tests/team.test.js @@ -171,142 +171,142 @@ describe("POST create team", function () { }); }); -// describe("PATCH change team", function () { -// it("should FAIL to join a hacker to a team due to lack of authentication", function (done) { -// chai.request(server.app) -// .patch(`/api/team/join/`) -// .type("application/json") -// .send({ -// teamName: "BronzeTeam", -// }) -// .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); -// res.body.should.have.property("data"); +describe("PATCH change team", function () { + it("should FAIL to join a hacker to a team due to lack of authentication", function (done) { + chai.request(server.app) + .patch(`/api/team/join/`) + .type("application/json") + .send({ + teamName: "BronzeTeam", + }) + .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); + res.body.should.have.property("data"); -// done(); -// }); -// }); + done(); + }); + }); -// it("should FAIL to join a volunteer to a team.", function (done) { -// util.auth.login(agent, util.account.Account5, (error) => { -// if (error) { -// agent.close(); -// return done(error); -// } -// return agent -// .patch(`/api/team/join/`) -// .type("application/json") -// .send({ -// teamName: "BronzeTeam", -// }) -// .end(function (err, res) { -// 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"); + it("should FAIL to join a volunteer to a team.", function (done) { + util.auth.login(agent, util.account.Account5, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .patch(`/api/team/join/`) + .type("application/json") + .send({ + teamName: "BronzeTeam", + }) + .end(function (err, res) { + 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(); -// }); -// }); -// }); + done(); + }); + }); + }); -// it("should FAIL to join a hacker to a team that doesn't exist.", function (done) { -// util.auth.login(agent, util.account.Account1, (error) => { -// if (error) { -// agent.close(); -// return done(error); -// } -// return agent -// .patch(`/api/team/join/`) -// .type("application/json") -// .send({ -// teamName: "NonExistTeam", -// }) -// .end(function (err, res) { -// res.should.have.status(404); -// res.should.be.json; -// res.body.should.have.property("message"); -// res.body.message.should.equal(Constants.Error.TEAM_404_MESSAGE); -// res.body.should.have.property("data"); + it("should FAIL to join a hacker to a team that doesn't exist.", function (done) { + util.auth.login(agent, util.account.Account1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .patch(`/api/team/join/`) + .type("application/json") + .send({ + teamName: "NonExistTeam", + }) + .end(function (err, res) { + res.should.have.status(404); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.TEAM_404_MESSAGE); + res.body.should.have.property("data"); -// done(); -// }); -// }); -// }); + done(); + }); + }); + }); -// it("should FAIL to join a hacker to a team that is full.", function (done) { -// util.auth.login(agent, util.account.Account1, (error) => { -// if (error) { -// agent.close(); -// return done(error); -// } -// return agent -// .patch(`/api/team/join/`) -// .type("application/json") -// .send({ -// teamName: "FullTeam", -// }) -// .end(function (err, res) { -// res.should.have.status(422); -// res.should.be.json; -// res.body.should.have.property("message"); -// res.body.message.should.equal(Constants.Error.TEAM_SIZE_422_MESSAGE); -// res.body.should.have.property("data"); + it("should FAIL to join a hacker to a team that is full.", function (done) { + util.auth.login(agent, util.account.Account1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .patch(`/api/team/join/`) + .type("application/json") + .send({ + teamName: "FullTeam", + }) + .end(function (err, res) { + res.should.have.status(422); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Error.TEAM_SIZE_422_MESSAGE); + res.body.should.have.property("data"); -// done(); -// }); -// }); -// }); + done(); + }); + }); + }); -// it("should SUCCEED and join a hacker without a team to a team.", function (done) { -// util.auth.login(agent, util.account.Account2, (error) => { -// if (error) { -// agent.close(); -// return done(error); -// } -// return agent -// .patch(`/api/team/join/`) -// .type("application/json") -// .send({ -// teamName: "BronzeTeam", -// }) -// .end(function (err, res) { -// res.should.have.status(200); -// res.should.be.json; -// res.body.should.have.property("message"); -// res.body.message.should.equal(Constants.Success.TEAM_JOIN); -// res.body.should.have.property("data"); + it("should SUCCEED and join a hacker without a team to a team.", function (done) { + util.auth.login(agent, util.account.Account2, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .patch(`/api/team/join/`) + .type("application/json") + .send({ + teamName: "BronzeTeam", + }) + .end(function (err, res) { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Success.TEAM_JOIN); + res.body.should.have.property("data"); -// done(); -// }); -// }); -// }); + done(); + }); + }); + }); -// it("should SUCCEED and join a hacker on a team to aother team.", function (done) { -// util.auth.login(agent, util.account.Account1, (error) => { -// if (error) { -// agent.close(); -// return done(error); -// } -// return agent -// .patch(`/api/team/join/`) -// .type("application/json") -// .send({ -// teamName: "SilverTeam", -// }) -// .end(function (err, res) { -// res.should.have.status(200); -// res.should.be.json; -// res.body.should.have.property("message"); -// res.body.message.should.equal(Constants.Success.TEAM_JOIN); -// res.body.should.have.property("data"); + it("should SUCCEED and join a hacker on a team to aother team.", function (done) { + util.auth.login(agent, util.account.Account1, (error) => { + if (error) { + agent.close(); + return done(error); + } + return agent + .patch(`/api/team/join/`) + .type("application/json") + .send({ + teamName: "SilverTeam", + }) + .end(function (err, res) { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property("message"); + res.body.message.should.equal(Constants.Success.TEAM_JOIN); + res.body.should.have.property("data"); -// done(); -// }); -// }); -// }); -// }); \ No newline at end of file + done(); + }); + }); + }); +}); \ No newline at end of file From 532a8068b2201e55aea49fed55c32c16a1d927bb Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Fri, 4 Jan 2019 20:19:01 -0500 Subject: [PATCH 08/13] fix git merge mistake --- constants/success.constant.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/constants/success.constant.js b/constants/success.constant.js index 4a55a285..bfbc6717 100644 --- a/constants/success.constant.js +++ b/constants/success.constant.js @@ -76,16 +76,8 @@ module.exports = { TEAM_GET_BY_ID: TEAM_GET_BY_ID, TEAM_CREATE: TEAM_CREATE, - << - << << < HEAD - TEAM_READ: TEAM_READ, - TEAM_JOIN: TEAM_JOIN, - === - === = TEAM_JOIN: TEAM_JOIN, TEAM_READ: TEAM_READ, - >>> - >>> > develop VOLUNTEER_CREATE: VOLUNTEER_CREATE, }; \ No newline at end of file From e27a72eda6a4eabfd80a565fba81e84bf9503c51 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Fri, 4 Jan 2019 20:33:29 -0500 Subject: [PATCH 09/13] Remove testing code, make sure create also updates hacker --- middlewares/team.middleware.js | 15 ++++++++++++++- services/team.service.js | 7 +------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/middlewares/team.middleware.js b/middlewares/team.middleware.js index b0805796..2767408d 100644 --- a/middlewares/team.middleware.js +++ b/middlewares/team.middleware.js @@ -71,6 +71,19 @@ async function createTeam(req, res, next) { }); } + for (const hackerId of teamDetails.members) { + const hacker = await Services.Hacker.updateOne(hackerId, { + teamId: team._id + }); + + if (!hacker) { + return res.status(500).json({ + message: Constants.Error.HACKER_UPDATE_500_MESSAGE, + data: {} + }); + } + } + req.body.team = team; return next(); } @@ -267,7 +280,7 @@ function parseTeam(req, res, next) { async function parseNewTeam(req, res, next) { const teamDetails = { - // _id: mongoose.Types.ObjectId(), + _id: mongoose.Types.ObjectId(), name: req.body.name, members: [], devpostURL: req.body.devpostURL, diff --git a/services/team.service.js b/services/team.service.js index 9257e7ba..274a41c2 100644 --- a/services/team.service.js +++ b/services/team.service.js @@ -35,12 +35,7 @@ async function createTeam(teamDetails) { const team = new Team(teamDetails); - await Team.init(); - - delete teamDetails._id; - - // return team.save(); - return Team.create(teamDetails); + return team.save(); } /** From 28e60259ad2e273a994a254f1005aa0143557f51 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Fri, 4 Jan 2019 20:35:33 -0500 Subject: [PATCH 10/13] docs --- docs/api/api_data.js | 9 +-------- docs/api/api_data.json | 9 +-------- docs/api/api_project.js | 30 +++++++++++++++--------------- docs/api/api_project.json | 30 +++++++++++++++--------------- 4 files changed, 32 insertions(+), 46 deletions(-) diff --git a/docs/api/api_data.js b/docs/api/api_data.js index ee4a109b..20bd2f55 100644 --- a/docs/api/api_data.js +++ b/docs/api/api_data.js @@ -2137,7 +2137,7 @@ define({ { "type": "post", "url": "/team/", - "title": "create a new team", + "title": "create a new team consisting of only the logged in user", "name": "createTeam", "group": "Team", "version": "0.0.8", @@ -2150,13 +2150,6 @@ define({ "field": "name", "description": "

Name of the team.

" }, - { - "group": "body", - "type": "MongoID[]", - "optional": true, - "field": "members", - "description": "

Array of members in team.

" - }, { "group": "body", "type": "String", diff --git a/docs/api/api_data.json b/docs/api/api_data.json index 716bc782..cfb379df 100644 --- a/docs/api/api_data.json +++ b/docs/api/api_data.json @@ -2136,7 +2136,7 @@ { "type": "post", "url": "/team/", - "title": "create a new team", + "title": "create a new team consisting of only the logged in user", "name": "createTeam", "group": "Team", "version": "0.0.8", @@ -2149,13 +2149,6 @@ "field": "name", "description": "

Name of the team.

" }, - { - "group": "body", - "type": "MongoID[]", - "optional": true, - "field": "members", - "description": "

Array of members in team.

" - }, { "group": "body", "type": "String", diff --git a/docs/api/api_project.js b/docs/api/api_project.js index 943e5b3e..0e8c6e6d 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-04T19:05:11.619Z", - "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-05T01:35:07.317Z", + "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 08ac760c..6f2d6d2e 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-04T19:05:11.619Z", - "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-05T01:35:07.317Z", + "url": "http://apidocjs.com", + "version": "0.17.7" + } } \ No newline at end of file From a8a640c9943a7873a8cf2a95a8ff5e8aa8560ba5 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Mon, 7 Jan 2019 14:19:25 -0500 Subject: [PATCH 11/13] Remove test index --- models/team.model.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/models/team.model.js b/models/team.model.js index dfbc1749..16743dc0 100644 --- a/models/team.model.js +++ b/models/team.model.js @@ -22,10 +22,6 @@ const TeamSchema = new mongoose.Schema({ projectName: String }); -TeamSchema.index({ - name: 1 -}); - function validateTeamSize(membersArr) { return membersArr.length <= Constants.MAX_TEAM_SIZE; } From 29beb978125789ca74478739124ce3a52beead08 Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Mon, 7 Jan 2019 14:32:09 -0500 Subject: [PATCH 12/13] re-add index on team name --- models/team.model.js | 1 + 1 file changed, 1 insertion(+) diff --git a/models/team.model.js b/models/team.model.js index 16743dc0..9905ab20 100644 --- a/models/team.model.js +++ b/models/team.model.js @@ -7,6 +7,7 @@ const TeamSchema = new mongoose.Schema({ name: { type: String, required: true, + unique: true, }, members: { type: [{ From 0a517e385b91ab170c9cae59a4b6b562111540dc Mon Sep 17 00:00:00 2001 From: Richard Zhang Date: Mon, 7 Jan 2019 14:47:23 -0500 Subject: [PATCH 13/13] fix merge issue --- tests/util/team.test.util.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/util/team.test.util.js b/tests/util/team.test.util.js index 62b44986..66506f42 100644 --- a/tests/util/team.test.util.js +++ b/tests/util/team.test.util.js @@ -12,6 +12,7 @@ const duplicateTeamName1 = { }; const newTeam1 = { + "_id": mongoose.Types.ObjectId(), "name": "BronzeTeam1", "projectName": "YetAnotherProject" };