From 98ccd87293f24aefa5590d2d2b663ce9294f0ada Mon Sep 17 00:00:00 2001 From: Pierre Theo Klein Date: Sun, 26 Jul 2020 12:38:47 -0400 Subject: [PATCH 1/4] Fix hasOwnProperty vulnerability (see https://eslint.org/docs/rules/no-prototype-builtins) --- constants/role.constant.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/constants/role.constant.js b/constants/role.constant.js index 9aa1a707..716cf182 100644 --- a/constants/role.constant.js +++ b/constants/role.constant.js @@ -154,13 +154,13 @@ function createAllSingularRoles() { // i is unique integer so that objectId is constant var i = 1000000; for (let routeGroupKey in allRoutes) { - if (!allRoutes.hasOwnProperty(routeGroupKey)) { + if (!Object.prototype.hasOwnProperty.call(allRoutes, routeGroupKey)) { continue; } const routeGroup = allRoutes[routeGroupKey]; for (let routeKey in routeGroup) { - if (!routeGroup.hasOwnProperty(routeKey)) { + if (!Object.prototype.hasOwnProperty.call(routeGroup, routeKey)) { continue; } @@ -197,7 +197,7 @@ function createAllRoles() { const singularRoles = createAllSingularRoles(); for (let role in singularRoles) { - if (!singularRoles.hasOwnProperty(role)) { + if (!Object.prototype.hasOwnProperty.call(singularRoles, role)) { continue; } allRolesObject[role] = singularRoles[role]; From e8b805472971c96fa955bfa1f234ac07c5585715 Mon Sep 17 00:00:00 2001 From: Pierre Theo Klein Date: Sun, 26 Jul 2020 14:29:20 -0400 Subject: [PATCH 2/4] Add _id value to all route objects, starting at 100 and moving upwards. Add warning at top of file to maintain naming standard. --- constants/routes.constant.js | 224 ++++++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 69 deletions(-) diff --git a/constants/routes.constant.js b/constants/routes.constant.js index e9c21ed0..9a0dda56 100644 --- a/constants/routes.constant.js +++ b/constants/routes.constant.js @@ -1,296 +1,376 @@ "use strict"; + +/** + * ===***===***===***===***===***===***===***===***=== + * ===***=== PLEASE READ BEFORE EDITING ===***=== + * ===***===***===***===***===***===***===***===***=== + * + * If you are adding a route to this list, update this number + * next avaiable createFromTime value: 165 + * + * If you are deleting a route from this list, please add the ID to the list of 'reserved' IDs, + * so that we don't accidentally assign someone to a given ID. + * reserved createFromTime values: + */ + const Constants = require("./general.constant"); +const mongoose = require("mongoose"); const authRoutes = { login: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/auth/login" + uri: "/api/auth/login", + _id: mongoose.Types.ObjectId.createFromTime(100) }, logout: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/auth/logout" + uri: "/api/auth/logout", + _id: mongoose.Types.ObjectId.createFromTime(101) }, getSelfRoleBindindings: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/auth/rolebindings/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/auth/rolebindings/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(102) }, getAnyRoleBindings: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/auth/rolebindings/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/auth/rolebindings/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(103) }, changePassword: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/auth/password/change" + uri: "/api/auth/password/change", + _id: mongoose.Types.ObjectId.createFromTime(104) } }; const accountRoutes = { getSelf: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/account/self" + uri: "/api/account/self", + _id: mongoose.Types.ObjectId.createFromTime(105) }, getSelfById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/account/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/account/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(106) }, getAnyById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/account/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/account/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(107) }, post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/account/" + uri: "/api/account/", + _id: mongoose.Types.ObjectId.createFromTime(108) }, patchSelfById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/account/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/account/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(109) }, patchAnyById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/account/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/account/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(110) }, inviteAccount: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/account/invite" + uri: "/api/account/invite", + _id: mongoose.Types.ObjectId.createFromTime(111) } }; const hackerRoutes = { getSelf: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/self/" + uri: "/api/hacker/self/", + _id: mongoose.Types.ObjectId.createFromTime(112) }, getSelfById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(113) }, getAnyById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(114) }, getSelfByEmail: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/email/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/email/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(115) }, getAnyByEmail: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/email/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/email/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(116) }, getSelfResumeById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(117) }, getAnyResumeById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(118) }, post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/" + uri: "/api/hacker/", + _id: mongoose.Types.ObjectId.createFromTime(119) }, postSelfResumeById: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(120) }, postAnyResumeById: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/resume/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(121) }, patchSelfById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(122) }, patchAnyById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(123) }, patchAnyStatusById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/status/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/status/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(124) }, patchSelfStatusById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/status/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/status/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(125) }, patchSelfCheckInById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/checkin/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/checkin/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(126) }, patchAnyCheckInById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/checkin/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/checkin/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(127) }, patchSelfConfirmationById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/hacker/confirmation/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/confirmation/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(128) }, patchAcceptHackerById: { requestType: Constants.REQUEST_TYPES.PATCH, uri: "/api/hacker/accept/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(129) }, patchAcceptHackerByEmail: { requestType: Constants.REQUEST_TYPES.PATCH, uri: "/api/hacker/acceptEmail/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(130) }, postAnySendWeekOfEmail: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/email/weekOf/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/email/weekOf/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(131) }, postSelfSendWeekOfEmail: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/email/weekOf/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/email/weekOf/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(132) }, postAnySendDayOfEmail: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/email/dayOf/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/hacker/email/dayOf/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(133) }, postSelfSendDayOfEmail: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/hacker/email/dayOf/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/hacker/email/dayOf/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(134) } }; const travelRoutes = { getSelf: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/travel/self/" + uri: "/api/travel/self/", + _id: mongoose.Types.ObjectId.createFromTime(135) }, getSelfById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/travel/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/travel/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(136) }, getAnyById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/travel/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/travel/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(137) }, getSelfByEmail: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/travel/email/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/travel/email/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(138) }, getAnyByEmail: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/travel/email/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/travel/email/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(139) }, post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/travel/" + uri: "/api/travel/", + _id: mongoose.Types.ObjectId.createFromTime(140) }, patchAnyStatusById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/travel/status/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/travel/status/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(141) }, patchAnyOfferById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/travel/offer/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/travel/offer/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(142) } -} +}; const sponsorRoutes = { getSelf: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/sponsor/self/" + uri: "/api/sponsor/self/", + _id: mongoose.Types.ObjectId.createFromTime(143) }, getSelfById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(144) }, getAnyById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(145) }, post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/sponsor/" + uri: "/api/sponsor/", + _id: mongoose.Types.ObjectId.createFromTime(146) }, patchSelfById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(147) }, patchAnyById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/sponsor/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(148) } }; const teamRoutes = { get: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/team/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/team/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(149) }, post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/team/" + uri: "/api/team/", + _id: mongoose.Types.ObjectId.createFromTime(150) }, join: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/team/join/" + uri: "/api/team/join/", + _id: mongoose.Types.ObjectId.createFromTime(151) }, patchSelfById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/team/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/team/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(152) }, patchAnyById: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/team/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/team/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(153) }, leave: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/team/leave/" + uri: "/api/team/leave/", + _id: mongoose.Types.ObjectId.createFromTime(154) } }; const volunteerRoutes = { getSelfById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/volunteer/" + Constants.ROLE_CATEGORIES.SELF + uri: "/api/volunteer/" + Constants.ROLE_CATEGORIES.SELF, + _id: mongoose.Types.ObjectId.createFromTime(155) }, getAnyById: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/volunteer/" + Constants.ROLE_CATEGORIES.ALL + uri: "/api/volunteer/" + Constants.ROLE_CATEGORIES.ALL, + _id: mongoose.Types.ObjectId.createFromTime(156) }, post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/volunteer/" + uri: "/api/volunteer/", + _id: mongoose.Types.ObjectId.createFromTime(157) } }; const roleRoutes = { post: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/role/" + uri: "/api/role/", + _id: mongoose.Types.ObjectId.createFromTime(158) } }; const searchRoutes = { get: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/search/" + uri: "/api/search/", + _id: mongoose.Types.ObjectId.createFromTime(159) } }; const staffRoutes = { hackerStats: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/hacker/stats" + uri: "/api/hacker/stats", + _id: mongoose.Types.ObjectId.createFromTime(160) }, postInvite: { requestType: Constants.REQUEST_TYPES.POST, - uri: "/api/account/invite" + uri: "/api/account/invite", + _id: mongoose.Types.ObjectId.createFromTime(161) }, getInvite: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/account/invite" + uri: "/api/account/invite", + _id: mongoose.Types.ObjectId.createFromTime(162) } }; const settingsRoutes = { getSettings: { requestType: Constants.REQUEST_TYPES.GET, - uri: "/api/settings" + uri: "/api/settings", + _id: mongoose.Types.ObjectId.createFromTime(163) }, patchSettings: { requestType: Constants.REQUEST_TYPES.PATCH, - uri: "/api/settings" + uri: "/api/settings", + _id: mongoose.Types.ObjectId.createFromTime(164) } }; @@ -310,23 +390,29 @@ const allRoutes = { /** * returns all the routes as a list - * @return {{requestType: string, uri: string}[]} + * @param {boolean} includeId whether to include _id in the returned route object. + * @return {{requestType: string, uri: string, id?: ObjectId}[]} */ -function listAllRoutes() { +function listAllRoutes(includeId = true) { let routes = []; for (let routeGroupKey in allRoutes) { - if (!allRoutes.hasOwnProperty(routeGroupKey)) { + if (!Object.prototype.hasOwnProperty.call(allRoutes, routeGroupKey)) { continue; } const routeGroup = allRoutes[routeGroupKey]; for (let routeKey in routeGroup) { - if (!routeGroup.hasOwnProperty(routeKey)) { + if (!Object.prototype.hasOwnProperty.call(routeGroup, routeKey)) { continue; } - const route = routeGroup[routeKey]; + const route = {}; + // copy only over the attributes that we care about + route.requestType = routeGroup[routeKey].requestType; + route.uri = routeGroup[routeKey].uri; + if (includeId) route._id = routeGroup[routeKey]._id; + routes.push(route); } } From 6efcb826a95098d16eebdd3482d0c81bf227cbbf Mon Sep 17 00:00:00 2001 From: Pierre Theo Klein Date: Sun, 26 Jul 2020 14:30:05 -0400 Subject: [PATCH 3/4] Change role.constant.js to use the new _id attribute so that ids are deterministic between two runs of npm run seed. --- constants/role.constant.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/constants/role.constant.js b/constants/role.constant.js index 716cf182..dfee5c3e 100644 --- a/constants/role.constant.js +++ b/constants/role.constant.js @@ -151,8 +151,6 @@ function createAllSingularRoles() { const allRoutes = Constants.Routes.allRoutes; let roles = []; - // i is unique integer so that objectId is constant - var i = 1000000; for (let routeGroupKey in allRoutes) { if (!Object.prototype.hasOwnProperty.call(allRoutes, routeGroupKey)) { continue; @@ -160,18 +158,19 @@ function createAllSingularRoles() { const routeGroup = allRoutes[routeGroupKey]; for (let routeKey in routeGroup) { + // Iterating through the attributes in the routeGroup object if (!Object.prototype.hasOwnProperty.call(routeGroup, routeKey)) { + // Avoid all prototype attributes continue; } let role = { - _id: mongoose.Types.ObjectId(i), + _id: routeGroup[routeKey]._id, name: routeKey + routeGroupKey, routes: routeGroup[routeKey] }; let roleName = role.name; roles[roleName] = role; - i -= 1; } } From 6b02db171560a093bb2fd347fbbe79252e4d132b Mon Sep 17 00:00:00 2001 From: Pierre Theo Klein Date: Sun, 26 Jul 2020 15:25:49 -0400 Subject: [PATCH 4/4] Update architecture documentation --- docs/architecture.md | 49 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 952ee097..4cf2bbb2 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -28,12 +28,13 @@ We use a custom implementation for authorization, which relies heavily on the de #### `Route` -A `Route`, which is a component of a `Role`, is defined by its uri path, its query parameters in the uri path, and the HTTP verb used to access it: +A `Route`, which is a component of a `Role`, is defined by its uri path, its query parameters in the uri path, the HTTP verb used to access it, and and `_id`: ```json { "uri": "/api/sponsor/", "requestType": "POST", + "_id": "000000010000000000000000" } ``` @@ -53,6 +54,45 @@ A `Role` is a collection of `Routes`, and a unique name (such as `hacker`, or `s _Note here that the parameter `routes` is a list of `Route` objects described in the previous section._ +##### In our code-base, we have a auto-generated list of `single roles` and a custom list of `user roles` + +`single roles` are roles that give permissions for one specific URI and request type. Every route has a `single role`. + +```json +{ + "_id": "000000010000000000000000", + "name": "postAccount", + "routes": [{ + "uri": "/api/account/", + "requestType": "POST", + "_id": "000000010000000000000000", + }] +} +``` + +`user roles` are syntactically the same as custom roles that give permissions for a collection of URIs and request types. These are essentially collections of routes that a given user needs access to in order to properly function with the API. + +```json +{ + "_id": "000000020000000000000000", + "name": "Account", + "routes": [{ + "uri": "/api/account/", + "requestType": "POST", + "_id": "000000010000000000000000", + }, + { + "uri": "/api/account/:SELF", + "requestType": "GET", + "_id": "000000030000000000000000", + }, + // etc. + ] +} +``` + +Note that for each route in the `user role`, you have access to the `single role` document's `_id`! + #### `RoleBinding` A `RoleBinding` is a mapping between an `account` and a `Role`. In this way, we can say that an account has a certain set of allowed actions, defined by the `Role`. An `account` can have a `RoleBinding` to multiple `Roles`. @@ -174,15 +214,18 @@ The http request that this would translate to is: ``` ### Error Codes and Messages + Error messages are in the error.constant.js file. The error constants are of the for TYPE_HTTPCODE_MESSAGE. For example, HACKER_404_MESSAGE. When creating a response, use an existing error message, or create a new one. An example: -``` + +```js next({ status: 422, message: Constants.Error.ACCOUNT_DUPLICATE_422_MESSAGE, error: {...} }); ``` -Note that the error status and the HTTPCODE in the error constant name are the same. + +Note that the error status and the HTTPCODE in the error constant name are the same. Error codes currently in use are: 401 - Invalid authentication