From f0c65e039ab07346c26f360cedb39c589f7d23ca Mon Sep 17 00:00:00 2001 From: allennatang Date: Thu, 24 Oct 2024 18:36:44 -0400 Subject: [PATCH 1/5] Updated package.json with Windows-specific commands --- package-lock.json | 2 +- package.json | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e7587c64..b9331981 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "eslint": "8.56.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-prettier": "5.1.3", - "mocha": "^10.0.0", + "mocha": "^10.2.0", "nodemon": "^3.0.2", "prettier": "3.1.1" } diff --git a/package.json b/package.json index cbc503c5..4b49908e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "deploy": "NODE_ENV=deployment node ./bin/www.js", "debug": "DEBUG=hackboard:* NODE_ENV=test nodemon --ignore gcp_creds.json ./bin/www.js", "test": "DEBUG=hackboard:* NODE_ENV=test mocha -r dotenv/config --reporter spec tests/**.js --exit", + "test-windows": "DEBUG=hackboard:* SET NODE_ENV=test & mocha -r dotenv/config --reporter spec tests/**.js --exit", "seed": "NODE_ENV=test node ./seed/index.js", + "seed-windows": "SET NODE_ENV=test & node ./seed/index.js", "docs": "apidoc -i ./routes -o ./docs/api/", "format": "prettier --write '**/*.js'", "lint": "eslint --fix '**/*.js'" From 97aed245eb0b412584676b9275228050885211ea Mon Sep 17 00:00:00 2001 From: allennatang Date: Thu, 31 Oct 2024 22:20:48 -0400 Subject: [PATCH 2/5] Changed hacker account's 'birthdate' field to 'age' #936 --- docs/api/api_data.js | 22 +++++----- docs/api/api_data.json | 22 +++++----- docs/standards.md | 2 +- middlewares/account.middleware.js | 4 +- middlewares/validators/account.validator.js | 4 +- middlewares/validators/validator.helper.js | 45 +++++++++++++++++++++ models/account.model.js | 19 ++++----- package.json | 2 +- routes/api/account.js | 15 ++++--- services/hacker.service.js | 8 +++- tests/util/account.test.util.js | 11 ++--- 11 files changed, 102 insertions(+), 52 deletions(-) diff --git a/docs/api/api_data.js b/docs/api/api_data.js index 25e0c5a6..3bfaa726 100644 --- a/docs/api/api_data.js +++ b/docs/api/api_data.js @@ -60,10 +60,10 @@ define({ "api": [ }, { "group": "body", - "type": "String", + "type": "Number", "optional": false, - "field": "birthDate", - "description": "

a Date parsable string.

" + "field": "age", + "description": "

The user's age.

" }, { "group": "body", @@ -86,7 +86,7 @@ define({ "api": [ "examples": [ { "title": "Request-Example:", - "content": "{ \n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"password\":\"hunter2\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"birthDate\":\"10/30/1997\"\n}", + "content": "{ \n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"password\":\"hunter2\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"age\":23,\n}", "type": "json" } ] @@ -113,7 +113,7 @@ define({ "api": [ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account creation successful\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account creation successful\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] @@ -195,7 +195,7 @@ define({ "api": [ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account found by user id\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account found by user id\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] @@ -379,7 +379,7 @@ define({ "api": [ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account found by user email\", \n \"data\": {\n \t\"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account found by user email\", \n \"data\": {\n \t\"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] @@ -466,10 +466,10 @@ define({ "api": [ }, { "group": "body", - "type": "String", + "type": "Number", "optional": true, - "field": "birthDate", - "description": "

A Date parsable string.

" + "field": "age", + "description": "

The user's age.

" }, { "group": "body", @@ -517,7 +517,7 @@ define({ "api": [ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account update successful.\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\": \"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account update successful.\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\": \"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] diff --git a/docs/api/api_data.json b/docs/api/api_data.json index cfc8a3ab..685b3dec 100644 --- a/docs/api/api_data.json +++ b/docs/api/api_data.json @@ -60,10 +60,10 @@ }, { "group": "body", - "type": "String", + "type": "Number", "optional": false, - "field": "birthDate", - "description": "

a Date parsable string.

" + "field": "age", + "description": "

The user's age.

" }, { "group": "body", @@ -86,7 +86,7 @@ "examples": [ { "title": "Request-Example:", - "content": "{ \n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"password\":\"hunter2\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"birthDate\":\"10/30/1997\"\n}", + "content": "{ \n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"password\":\"hunter2\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"age\":23,\n}", "type": "json" } ] @@ -113,7 +113,7 @@ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account creation successful\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account creation successful\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] @@ -195,7 +195,7 @@ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account found by user id\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account found by user id\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \"gender\":\"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] @@ -379,7 +379,7 @@ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account found by user email\", \n \"data\": {\n \t\"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account found by user email\", \n \"data\": {\n \t\"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\":\"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] @@ -466,10 +466,10 @@ }, { "group": "body", - "type": "String", + "type": "Number", "optional": true, - "field": "birthDate", - "description": "

A Date parsable string.

" + "field": "age", + "description": "

The user's age.

" }, { "group": "body", @@ -517,7 +517,7 @@ "examples": [ { "title": "Success-Response: ", - "content": "{\n \"message\": \"Account update successful.\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\": \"Male\",\n \"birthDate\":Date(\"10/30/1997\")\n }\n }", + "content": "{\n \"message\": \"Account update successful.\", \n \"data\": {\n \"id\": ObjectId(\"5bff8b9f3274cf001bc71048\"),\n \t\"firstName\": \"Theo\",\n \"lastName\":\"Klein\",\n \"pronoun\":\"he/him\",\n \"email\":\"theo@klein.com\",\n \"phoneNumber\":1234567890,\n \t\"gender\": \"Male\",\n \"age\":23,\n }\n }", "type": "object" } ] diff --git a/docs/standards.md b/docs/standards.md index 08be5dc4..ea7c5bf4 100644 --- a/docs/standards.md +++ b/docs/standards.md @@ -352,7 +352,7 @@ module.exports = { VALIDATOR.regexValidator("body", "email", true, Constants.EMAIL_REGEX), VALIDATOR.alphaArrayValidator("body", "dietaryRestrictions", true), VALIDATOR.enumValidator("body", "shirtSize", Constants.SHIRT_SIZES, true), - VALIDATOR.dateValidator("body", "birthDate", true), + VALIDATOR.ageValidator("body", "age", true), VALIDATOR.phoneNumberValidator("body", "phoneNumber", true) ], }; diff --git a/middlewares/account.middleware.js b/middlewares/account.middleware.js index c57f9dfb..95763e02 100644 --- a/middlewares/account.middleware.js +++ b/middlewares/account.middleware.js @@ -55,7 +55,7 @@ function parseAccount(req, res, next) { password: Services.Account.hashPassword(req.body.password), dietaryRestrictions: req.body.dietaryRestrictions, gender: req.body.gender, - birthDate: req.body.birthDate, + age: req.body.age, phoneNumber: req.body.phoneNumber }; @@ -67,7 +67,7 @@ function parseAccount(req, res, next) { delete req.body.password; delete req.body.dietaryRestrictions; delete req.body.gender; - delete req.body.birthDate; + delete req.body.age; delete req.body.phoneNumber; req.body.accountDetails = accountDetails; diff --git a/middlewares/validators/account.validator.js b/middlewares/validators/account.validator.js index 51ada35b..b20a8221 100644 --- a/middlewares/validators/account.validator.js +++ b/middlewares/validators/account.validator.js @@ -18,7 +18,7 @@ module.exports = { process.env.JWT_CONFIRM_ACC_SECRET, true ), - VALIDATOR.dateValidator("body", "birthDate", false), + VALIDATOR.ageValidator("body", "age", false), VALIDATOR.phoneNumberValidator("body", "phoneNumber", true) ], updateAccountValidator: [ @@ -29,7 +29,7 @@ module.exports = { VALIDATOR.regexValidator("body", "email", true, Constants.EMAIL_REGEX), VALIDATOR.alphaArrayValidator("body", "dietaryRestrictions", true), VALIDATOR.stringValidator("body", "gender", true), - VALIDATOR.dateValidator("body", "birthDate", true), + VALIDATOR.ageValidator("body", "age", true), VALIDATOR.phoneNumberValidator("body", "phoneNumber", true) ], inviteAccountValidator: [ diff --git a/middlewares/validators/validator.helper.js b/middlewares/validators/validator.helper.js index 5e293648..d4da9bb9 100644 --- a/middlewares/validators/validator.helper.js +++ b/middlewares/validators/validator.helper.js @@ -839,6 +839,50 @@ function dateValidator(fieldLocation, fieldname, optional = true) { isValid: date }); } +} + +/** + * Validates that field must be a valid age between 0 and 100. + * @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 ageValidator(fieldLocation, fieldname, optional = true) { + const age = setProperValidationChainBuilder( + fieldLocation, + fieldname, + "Invalid age" + ); + if (optional) { + return age + .optional({ + checkFalsy: true + }) + .custom((value) => { + // Check if the value is empty or undefined + if (!value) return true; // Allow empty values if optional + + // Validate age: must be a number between 0 and 100 + const ageNumber = Number(value); + return !isNaN(ageNumber) && ageNumber >= 0 && ageNumber <= 100; + }) + .withMessage({ + message: "Age is not valid. It must be between 0 and 100.", + isValid: age + }); + } else { + return age + .exists() + .withMessage("Age field must be specified") // Ensure field exists + .custom((value) => { + const ageNumber = Number(value); + return !isNaN(ageNumber) && ageNumber >= 0 && ageNumber <= 100; + }) + .withMessage({ + message: "Age is not valid. It must be between 0 and 100.", + isValid: age + }); + } } /** @@ -1027,6 +1071,7 @@ module.exports = { searchSortValidator: searchSortValidator, phoneNumberValidator: phoneNumberValidator, dateValidator: dateValidator, + ageValidator: ageValidator, enumValidator: enumValidator, routesValidator: routesValidator, stringValidator: stringValidator diff --git a/models/account.model.js b/models/account.model.js index 047c8bc0..fe83490f 100644 --- a/models/account.model.js +++ b/models/account.model.js @@ -46,8 +46,8 @@ const AccountSchema = new mongoose.Schema({ enum: Constants.EXTENDED_USER_TYPES, default: Constants.HACKER }, - birthDate: { - type: Date, + age: { + type: Number, required: true }, phoneNumber: { @@ -85,15 +85,16 @@ AccountSchema.methods.isSponsor = function() { this.accountType == Constants.SPONSOR ); }; + /** - * Calculates the user's age + * CHANGED BIRTHDATE TO AGE - Calculates the user's age */ -AccountSchema.methods.getAge = function() { - // birthday is a date - var ageDifMs = Date.now() - this.birthDate.getTime(); - var ageDate = new Date(ageDifMs); // miliseconds from epoch - return Math.abs(ageDate.getUTCFullYear() - 1970); -}; +// AccountSchema.methods.getAge = function() { +// // birthday is a date +// var ageDifMs = Date.now() - this.birthDate.getTime(); +// var ageDate = new Date(ageDifMs); // miliseconds from epoch +// return Math.abs(ageDate.getUTCFullYear() - 1970); +// }; //export the model module.exports = mongoose.model("Account", AccountSchema); diff --git a/package.json b/package.json index 4b49908e..bad02641 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "start": "DEBUG=hackboard:* NODE_ENV=development nodemon --ignore gcp_creds.json ./bin/www.js", - "start-windows": "set DEBUG=hackboard:* && set NODE_ENV=development && nodemon --ignore gcp_creds.json ./bin/www.js", + "start-windows": "set DEBUG=hackboard:* && set NODE_ENV=test && nodemon --ignore gcp_creds.json ./bin/www.js", "deploy": "NODE_ENV=deployment node ./bin/www.js", "debug": "DEBUG=hackboard:* NODE_ENV=test nodemon --ignore gcp_creds.json ./bin/www.js", "test": "DEBUG=hackboard:* NODE_ENV=test mocha -r dotenv/config --reporter spec tests/**.js --exit", diff --git a/routes/api/account.js b/routes/api/account.js index 7a41dbea..9481051b 100644 --- a/routes/api/account.js +++ b/routes/api/account.js @@ -43,7 +43,7 @@ module.exports = { "email":"theo@klein.com", "phoneNumber":1234567890, "gender":"Male", - "birthDate":Date("10/30/1997") + "age":23") } } * @apiError {string} message Error message @@ -72,7 +72,7 @@ module.exports = { * @apiParam (body) {String} gender Gender of the account creator. * @apiParam (body) {String[]} dietaryRestrictions Any dietary restrictions for the user. 'None' if there are no restrictions * @apiParam (body) {String} password The password of the account. - * @apiParam (body) {String} birthDate a Date parsable string. + * @apiParam (body) {Number} age The user's age. * @apiParam (body) {Number} [phoneNumber] the user's phone number, represented as a string. * @apiParam (header) {JWT} [token] the user's invite token. * @@ -85,7 +85,7 @@ module.exports = { "password":"hunter2", "phoneNumber":1234567890, "gender":"Male", - "birthDate":"10/30/1997" + "age:23" * } * * @apiSuccess {string} message Success message @@ -101,7 +101,7 @@ module.exports = { "email":"theo@klein.com", "phoneNumber":1234567890, "gender":"Male", - "birthDate":Date("10/30/1997") + "age:23") } } @@ -212,9 +212,8 @@ module.exports = { * @apiParam (body) {String} [pronoun] The pronoun of the account creator. * @apiParam (body) {String} [email] Email of the account. * @apiParam (body) {String} [gender] Gender of the account creator. - * @apiParam (body) {String} [birthDate] A Date parsable string. + * @apiParam (body) {String} [age] Age of the account creator. * @apiParam (body) {Number} [phoneNumber] The user's phone number, represented as a string. - * @apiParam (body) {String} [birthDate] a Date parsable string. * @apiParam (body) {String[]} [dietaryRestrictions] Any dietary restrictions for the user. 'None' if there are no restrictions * @apiParamExample {json} Request-Example: * { "gender": "Male" } @@ -233,7 +232,7 @@ module.exports = { "email":"theo@klein.com", "phoneNumber":1234567890, "gender": "Male", - "birthDate":Date("10/30/1997") + "age:23") } } @@ -280,7 +279,7 @@ module.exports = { "email":"theo@klein.com", "phoneNumber":1234567890, "gender":"Male", - "birthDate":Date("10/30/1997") + "age:23") } } diff --git a/services/hacker.service.js b/services/hacker.service.js index f47b43da..bd86f7e8 100644 --- a/services/hacker.service.js +++ b/services/hacker.service.js @@ -201,8 +201,12 @@ function getStats(hackers) { .shirtSize[hacker.application.accommodation.shirtSize] ? stats.shirtSize[hacker.application.accommodation.shirtSize] + 1 : 1; - const age = hacker.accountId.getAge(); - stats.age[age] = stats.age[age] ? stats.age[age] + 1 : 1; + + // CHANGED BIRTHDATE TO AGE + // const age = hacker.accountId.getAge(); + // stats.age[age] = stats.age[age] ? stats.age[age] + 1 : 1; + + stats.age[hacker.accountId.age] = stats.age[hacker.accountId.age] ? stats.age[age] + 1 : 1; const applicationDate = hacker._id .getTimestamp() // diff --git a/tests/util/account.test.util.js b/tests/util/account.test.util.js index ec521dee..4e8655f5 100644 --- a/tests/util/account.test.util.js +++ b/tests/util/account.test.util.js @@ -83,8 +83,9 @@ function generateRandomValue(atr) { return Constants.EXTENDED_USER_TYPES[ Math.floor(Math.random() * Constants.EXTENDED_USER_TYPES.length) ]; - case "birthDate": - return new Date(); + case "age": + // Generate a random age between 0 and 100 + return Math.floor(Math.random() * 101); // 0 to 100 case "phoneNumber": return Math.floor(Math.random() * 10000000000); } @@ -264,7 +265,7 @@ const waitlistedHacker0 = { gender: "Male", confirmed: true, accountType: Constants.HACKER, - birthDate: "1990-01-04", + age: 23, phoneNumber: 1000000004 }; @@ -280,7 +281,7 @@ const NonConfirmedAccount1 = { dietaryRestrictions: ["something1", "something2"], gender: "Male", confirmed: false, - birthDate: "1980-07-30", + age: 23, phoneNumber: 1001230236, accountType: Constants.HACKER }; @@ -315,7 +316,7 @@ const NoPhoneHackerAccount0 = { dietaryRestrictions: ["something1", "something2"], gender: "Male", confirmed: false, - birthDate: "1980-07-30", + age: "23", accountType: Constants.HACKER }; From 3306f593782e5e53b6c2ef49ada05c43df8c152f Mon Sep 17 00:00:00 2001 From: allennatang Date: Thu, 31 Oct 2024 22:20:48 -0400 Subject: [PATCH 3/5] Changed age type Number to type String --- docs/api/api_data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/api_data.js b/docs/api/api_data.js index 3bfaa726..36f55a34 100644 --- a/docs/api/api_data.js +++ b/docs/api/api_data.js @@ -60,7 +60,7 @@ define({ "api": [ }, { "group": "body", - "type": "Number", + "type": "String", "optional": false, "field": "age", "description": "

The user's age.

" From 62c2586b0fc66a9a21cdb8a1c8abac9f1714668d Mon Sep 17 00:00:00 2001 From: allennatang Date: Thu, 31 Oct 2024 22:20:48 -0400 Subject: [PATCH 4/5] Changed age type Number to type String #936 --- docs/api/api_data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/api_data.js b/docs/api/api_data.js index 3bfaa726..36f55a34 100644 --- a/docs/api/api_data.js +++ b/docs/api/api_data.js @@ -60,7 +60,7 @@ define({ "api": [ }, { "group": "body", - "type": "Number", + "type": "String", "optional": false, "field": "age", "description": "

The user's age.

" From 6923dc3d6452c33679a8e72d61b700d2cb4db189 Mon Sep 17 00:00:00 2001 From: allennatang Date: Thu, 14 Nov 2024 18:54:25 -0500 Subject: [PATCH 5/5] Added country of residence field to hacker application --- middlewares/validators/hacker.validator.js | 5 +++++ middlewares/validators/validator.helper.js | 5 +++++ models/hacker.model.js | 4 ++++ package.json | 9 ++++----- results.txt | Bin 0 -> 271012 bytes results2.txt | Bin 0 -> 289052 bytes routes/api/hacker.js | 10 ++++++++++ services/hacker.service.js | 7 +++++++ tests/hacker.test.js | 1 + tests/util/hacker.test.util.js | 16 ++++++++++++++++ 10 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 results.txt create mode 100644 results2.txt diff --git a/middlewares/validators/hacker.validator.js b/middlewares/validators/hacker.validator.js index 50078261..0199e2bd 100644 --- a/middlewares/validators/hacker.validator.js +++ b/middlewares/validators/hacker.validator.js @@ -251,6 +251,11 @@ module.exports = { "application.other.ethnicity", false ), + VALIDATOR.stringValidator( + "body", + "application.other.country", + false + ), VALIDATOR.booleanValidator( "body", "application.other.privacyPolicy", diff --git a/middlewares/validators/validator.helper.js b/middlewares/validators/validator.helper.js index d4da9bb9..54d0b7e8 100644 --- a/middlewares/validators/validator.helper.js +++ b/middlewares/validators/validator.helper.js @@ -392,6 +392,7 @@ function applicationValidator(fieldLocation, fieldname, optional = true) { shirtSize: false, other: false, ethnicity: false, + country: false, codeOfConduct: false, privacyPolicy: false }; @@ -439,6 +440,7 @@ function applicationValidator(fieldLocation, fieldname, optional = true) { hasValid.other = app.hasOwnProperty("other"); if (hasValid.other) { hasValid.ethnicity = app.other.hasOwnProperty("ethnicity"); + hasValid.country = app.other.hasOwnProperty("country"); hasValid.codeOfConduct = app.other.hasOwnProperty( "codeOfConduct" ); @@ -497,6 +499,7 @@ function applicationValidator(fieldLocation, fieldname, optional = true) { hasValid.shirtSize && hasValid.other && hasValid.ethnicity && + hasValid.country && hasValid.privacyPolicy && hasValid.codeOfConduct ); @@ -545,6 +548,7 @@ function applicationValidator(fieldLocation, fieldname, optional = true) { hasValid.other = app.hasOwnProperty("other"); if (hasValid.other) { hasValid.ethnicity = app.other.hasOwnProperty("ethnicity"); + hasValid.country = app.other.hasOwnProperty("country"); hasValid.codeOfConduct = app.other.hasOwnProperty( "codeOfConduct" ); @@ -603,6 +607,7 @@ function applicationValidator(fieldLocation, fieldname, optional = true) { hasValid.shirtSize && hasValid.other && hasValid.ethnicity && + hasValid.country && hasValid.privacyPolicy && hasValid.codeOfConduct ); diff --git a/models/hacker.model.js b/models/hacker.model.js index 291964e3..1b9fe608 100644 --- a/models/hacker.model.js +++ b/models/hacker.model.js @@ -103,6 +103,10 @@ const HackerSchema = new mongoose.Schema({ ], required: true }, + country: { + type: String, + required: true + }, privacyPolicy: { type: Boolean, required: true diff --git a/package.json b/package.json index bad02641..39c9d070 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,10 @@ "start": "DEBUG=hackboard:* NODE_ENV=development nodemon --ignore gcp_creds.json ./bin/www.js", "start-windows": "set DEBUG=hackboard:* && set NODE_ENV=test && nodemon --ignore gcp_creds.json ./bin/www.js", "deploy": "NODE_ENV=deployment node ./bin/www.js", - "debug": "DEBUG=hackboard:* NODE_ENV=test nodemon --ignore gcp_creds.json ./bin/www.js", - "test": "DEBUG=hackboard:* NODE_ENV=test mocha -r dotenv/config --reporter spec tests/**.js --exit", - "test-windows": "DEBUG=hackboard:* SET NODE_ENV=test & mocha -r dotenv/config --reporter spec tests/**.js --exit", - "seed": "NODE_ENV=test node ./seed/index.js", - "seed-windows": "SET NODE_ENV=test & node ./seed/index.js", + "debug": "DEBUG=hackboard:* NODE_ENV=development nodemon --ignore gcp_creds.json ./bin/www.js", + "test": "DEBUG=hackboard:* NODE_ENV=development mocha -r dotenv/config --reporter spec tests/**.js --exit", + "test-windows": "DEBUG=hackboard:* SET NODE_ENV=development & mocha -r dotenv/config --reporter spec tests/**.js --exit", + "seed": "NODE_ENV=development node ./seed/index.js", "docs": "apidoc -i ./routes -o ./docs/api/", "format": "prettier --write '**/*.js'", "lint": "eslint --fix '**/*.js'" diff --git a/results.txt b/results.txt new file mode 100644 index 0000000000000000000000000000000000000000..fb191fefa2214bfa15f19dc260231e3e014dd620 GIT binary patch literal 271012 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 K8zRQT*Z&7-Ka=wS literal 0 HcmV?d00001 diff --git a/results2.txt b/results2.txt new file mode 100644 index 0000000000000000000000000000000000000000..d4067efaddc6846f27a24aec879b6bd3fc738a22 GIT binary patch literal 289052 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 YGBi5yQ^_2SL@FGORt=4anDO=h0my}QZ~y=R literal 0 HcmV?d00001 diff --git a/routes/api/hacker.js b/routes/api/hacker.js index 77cb1d43..8d64c255 100644 --- a/routes/api/hacker.js +++ b/routes/api/hacker.js @@ -56,6 +56,7 @@ module.exports = { }, "status":"Applied", "ethnicity":["White or Caucasian"," Asian or Pacific Islander"], + "country":"Canada", "accountId":"5bff2a35e533b0f6562b4998", "school":"McPherson College", "gender":"Female", @@ -90,6 +91,7 @@ module.exports = { * @apiParam (body) {String} gender Gender of the hacker * @apiParam (body) {Number} travel Whether the hacker requires a bus for transportation * @apiParam (body) {String[]} ethnicity the ethnicities of the hacker + * @apiParam (body) {String} country Name of the country of residence of the hacker * @apiParam (body) {String[]} major the major of the hacker * @apiParam (body) {Number} graduationYear the graduation year of the hacker * @apiParam (body) {Boolean} codeOfConduct acceptance of the code of conduct @@ -122,6 +124,7 @@ module.exports = { "other:" { "gender": "male", "ethnicity": "Asian or Pacific Islander", + "country": "Canada", "privacyPolicy": true, "codeOfConduct": true, } @@ -170,6 +173,7 @@ module.exports = { "other:" { "gender": "male", "ethnicity": "Asian or Pacific Islander", + "country": "Canada", "privacyPolicy": true, "codeOfConduct": true, } @@ -235,6 +239,7 @@ module.exports = { gender: { "Male": 1, "Female": 9 }, travel: { "true": 7, "false": 3 }, ethnicity: { "White": 10, }, + country: {"Canada": 10}, jobInterest: { "Internship": 10 }, major: { "Computer Science": 10 }, graduationYear: { "2019": 10 }, @@ -435,6 +440,7 @@ module.exports = { * @apiParam (body) {String} [gender] Gender of the hacker * @apiParam (body) {Number} [travel] How much the hacker requires a bus for transportation * @apiParam (body) {String[]} [ethnicity] the ethnicities of the hacker + * @apiParam (body) {String} [country] Country of residence of the hacker * @apiParam (body) {String[]} [major] the major of the hacker * @apiParam (body) {Number} [graduationYear] the graduation year of the hacker * @apiParam (body) {Json} [application] The hacker's application @@ -466,6 +472,7 @@ module.exports = { "other:" { "gender": "male", "ethnicity": "Asian or Pacific Islander", + "country": "Canada", "privacyPolicy": true, "codeOfConduct": true, } @@ -514,6 +521,7 @@ module.exports = { "other:" { "gender": "male", "ethnicity": "Asian or Pacific Islander", + "country": "Canada", "privacyPolicy": true, "codeOfConduct": true, } @@ -591,6 +599,7 @@ module.exports = { "other:" { "gender": "male", "ethnicity": "Asian or Pacific Islander", + "country": "Canada", "privacyPolicy": true, "codeOfConduct": true, } @@ -664,6 +673,7 @@ module.exports = { "other:" { "gender": "male", "ethnicity": "Asian or Pacific Islander", + "country": "Canada", "privacyPolicy": true, "codeOfConduct": true, } diff --git a/services/hacker.service.js b/services/hacker.service.js index bd86f7e8..37531700 100644 --- a/services/hacker.service.js +++ b/services/hacker.service.js @@ -132,6 +132,7 @@ function getStats(hackers) { gender: {}, travel: {}, ethnicity: {}, + country: {}, jobInterest: {}, fieldOfStudy: {}, graduationYear: {}, @@ -177,6 +178,12 @@ function getStats(hackers) { : 1; } + stats.country[hacker.application.other.country] = stats.country[ + hacker.application.other.country + ] + ? stats.country[hacker.application.other.country] + 1 + : 1; + stats.jobInterest[hacker.application.general.jobInterest] = stats .jobInterest[hacker.application.general.jobInterest] ? stats.jobInterest[hacker.application.general.jobInterest] + 1 diff --git a/tests/hacker.test.js b/tests/hacker.test.js index 6bd7bc69..b344e86d 100644 --- a/tests/hacker.test.js +++ b/tests/hacker.test.js @@ -1739,6 +1739,7 @@ describe("GET Hacker stats", function() { res.body.data.stats.should.have.property("gender"); res.body.data.stats.should.have.property("travel"); res.body.data.stats.should.have.property("ethnicity"); + res.body.data.stats.should.have.property("country"); res.body.data.stats.should.have.property("jobInterest"); res.body.data.stats.should.have.property("fieldOfStudy"); res.body.data.stats.should.have.property("graduationYear"); diff --git a/tests/util/hacker.test.util.js b/tests/util/hacker.test.util.js index 1eb310cb..98e36a1a 100644 --- a/tests/util/hacker.test.util.js +++ b/tests/util/hacker.test.util.js @@ -39,6 +39,7 @@ const TeamHacker0 = { }, other: { ethnicity: ["Native American"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -81,6 +82,7 @@ const TeamHacker1 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -123,6 +125,7 @@ const TeamHacker2 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -165,6 +168,7 @@ const TeamHacker3 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -207,6 +211,7 @@ const TeamHacker4 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -249,6 +254,7 @@ const NoTeamHacker0 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -288,6 +294,7 @@ const newHacker0 = { }, other: { ethnicity: ["Caucasian"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -327,6 +334,7 @@ const newHacker1 = { }, other: { ethnicity: ["African American"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -367,6 +375,7 @@ const invalidHacker0 = { }, other: { ethnicity: ["Caucasian"], + country: "Canada", // must accept code of conduct to be valid codeOfConduct: false, privacyPolicy: false @@ -404,6 +413,7 @@ const invalidHacker1 = { }, other: { ethnicity: ["Caucasian"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -446,6 +456,7 @@ const invalidHacker2 = { }, other: { ethnicity: ["Caucasian"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -487,6 +498,7 @@ const invalidHacker3 = { }, other: { ethnicity: ["Caucasian"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -529,6 +541,7 @@ const duplicateAccountLinkHacker0 = { }, other: { ethnicity: ["Caucasian"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -570,6 +583,7 @@ const waitlistedHacker0 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -612,6 +626,7 @@ const unconfirmedAccountHacker0 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true }, @@ -653,6 +668,7 @@ const unconfirmedAccountHacker1 = { }, other: { ethnicity: ["European"], + country: "Canada", codeOfConduct: true, privacyPolicy: true },