Skip to content

Instantly share code, notes, and snippets.

@rockchalkwushock
Created June 9, 2017 05:29
Show Gist options
  • Select an option

  • Save rockchalkwushock/55a208af39aa91cf2b89daacc4b4a491 to your computer and use it in GitHub Desktop.

Select an option

Save rockchalkwushock/55a208af39aa91cf2b89daacc4b4a491 to your computer and use it in GitHub Desktop.
Explanation of code for Rhonda
// The createNote conroller
// @see https://github.com/rockchalkwushock/note_dashboard/blob/master/api/modules/note/controller.js#L49
export const createNote = async (req, res, next) => {
const filteredBody = filterBody(req.body, config.WHITELIST.notes.create)
try {
const note = await Note.createNote(filteredBody, req.user._id)
return res.status(HTTPStatus.CREATED).json(note)
} catch (e) {
e.status = HTTPStatus.BAD_REQUEST
/* istanbul ignore next */
return next(e)
}
}
/*
So createNote is a function expression that is going to run asynchronously meaning this is a promise.
It takes in 3 params:
- request - the http request submitted by the user.
- response - the http response object we will modify and send back to the user.
- next - a funciton that handles the finalization of the promise.
@see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next
The first thing we do is take the data being submitted by the user in req.body & send it as a param to the
filterBody() method with the keys that we have whitelisted as the second param. This method will return an
object that is the data we expected from the user and nothing more (no malicious key/value pairs).
We now enter the try/catch block. We are going to pause the function and await the data that will
be returned from the method on our Note model because it is a promise. We store that data in
a variable to send back to the user.
The await keyword is just pausing the function and waiting for the promise to resolve or reject. Should the promise reject
the catch block will 'catch' the error & add the status key/value pair to the error object which will be returned to the user.
If the promise resloves then we return the success object to the user & the data has been created on the database.
*/
// Whitelist
// @see https://github.com/rockchalkwushock/note_dashboard/blob/master/api/configs/configuration.js#L9
/*
These are the properties we are expecting on the req.body object.
And the ONLY properties we are going to let through to the server
via the filterBody() method.
*/
const WHITELIST = {
notes: {
create: ['text', 'title'],
}
}
// filterBody()
// @see https://github.com/rockchalkwushock/note_dashboard/blob/master/api/utils/filterBody.js#L18
export const filterBody = (body, whitelist) => {
const items = {};
/*
Example:
body: {
text: "foo",
title: "bar",
malicious: "virus"
}
*/
// take req.body & give me back an array of the keys
// i.e. ["text", "title", "malicious"]
// @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Object.keys(body).forEach(key => {
/*
Whitelist:
create: ["text", "title"]
*/
/*
Does the key from body exist in the whitelist?
If yes then indexOf evaluates to >= 0
If no then indexOf evaluates to -1 and this key/value is not added to items.
*/
// @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf?v=example
if (whitelist.indexOf(key) >= 0) {
/*
NOTE: body.text evaluates to the value stored at that key!
Iteration 1: items.text = body.text
Iteration 2: items.title = body.title
Iteration 3: FAIL not present in whitelist evaluates as -1 which fails the if block.
*/
items[key] = body[key];
}
});
// Return the object of filtered key/value pairs.
return items;
}
// Note.createNote()
// @see https://github.com/rockchalkwushock/note_dashboard/blob/master/api/modules/note/model.js#L41
NoteSchema.statics = {
/*
take the filtered object & add the author value to it
then we pass this object to the create method that is native
to mongoose, creating the document in the database.
@see http://mongoosejs.com/docs/api.html#model_Model.create
NOTE: to create a note there must be an author because this is
an auth protected route if the userId present does not match our
database or their is no userId present this method will fail and
not add data (possibly malicious) to our database.
*/
createNote(args, userId) {
return this.create({
...args,
author: userId,
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment