create account

Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2) by gotgame

View this thread on: hive.blogpeakd.comecency.com
· @gotgame · (edited)
$20.52
Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)
### Repository

[https://github.com/nodejs/node](https://github.com/nodejs/node)

#### What Will I Learn

The codebase for this tutorial is based on [MEANie](https://github.com/cornflourblue/meanie) an open source content management system by [Jason Watmore](http://jasonwatmore.com/).

This is the third tutorial in the series of tutorials on building a content management system using the MEAN technology.

In the first two tutorials we created the backend server, some helper and controller modules for the application.

In this tutorial we are going to work on the remaining controller modules for the application features including

1.   Contact Controller
2.   Pages Controller
3.   Posts Controller
4.   Redirects Controller
5.   Users Controller


N.B;- LINK TO THE EARLIER TUTORIALS IN THIS SERIES CAN BE FOUND AT THE END OF THIS POST

### Requirements

-   [NodeJS and NPM](https://nodejs.org/en/download/package-manager/ ),
-   [Angular](https://angular.io/)
-   [MongoDB](https://www.mongodb.com/)
-   Text Editor

### Difficulty

-   Intermediate

### Tutorial Contents

#### Contact Controller

In the application we would need a contact feature so the non-admin users will be able to get in touch with the admin through e-mail.

To create a controller for our contact feature, first of all create a new directory in the controllers directory we created in the last tutorial.

Name the new directory `api`. Inside the new directory, add a new file `contact.controller.js`.

In the file we have 

```
var  config  =  require('config.json');

var  nodemailer  =  require('nodemailer');

var  express  =  require('express');

var  router  =  express.Router();

  

// routes

router.post('/', send);

  

module.exports  =  router;

  

function  send(req, res) {

	// email data and options

	var  mailOptions  = {

		from:  req.body.email,

		to:  config.contactEmail,

		subject:  req.body.subject,

		text:  req.body.message

	};

  

	// send mail

	var  transporter  =  nodemailer.createTransport();

	transporter.sendMail(mailOptions, function (err) {

		if (err) {

			console.log('error sending email', err);

			return  res.status(400).send(err);

		}

  

		res.sendStatus(200);

	});

}
```

`var  nodemailer  =  require('nodemailer');` will import `nodemailer`a popular JavaScript module for sending emails in Node.js applications.

`router.post('/', send);` is the route that handles the email body and it has a callback function `send`.

In the function `send` the first variable `mailOptions` is a JavaScript object containing the data required to initialize the email for sending.

`from:  req.body.email` holds the email address of the sender.

`to:  config.contactEmail` holds the address the email is sent to, the actual value for this can be found in the `config.json` file. To know more about the `config.json` check the first tutorial.

`subject:  req.body.subject` holds the title/header for the email to be sent

`text:  req.body.message` holds the actual email message.

`var  transporter  =  nodemailer.createTransport()` should contain the required details for the email provider account where the email is set to be received. 

The value for this section is relative, read more about this from [nodemailer documentation](https://nodemailer.com/transports/sendmail/).

`transporter.sendMail()` will handle the actual sending of the email given the parameter from the variable `mailOptions` and a callback function that handles any error that might arise during the email transfer.


#### Pages Controller

Creata a new file `pages.controller.js`, it will contain the following.

```
var  config  =  require('config.json');

var  _  =  require('lodash');

var  express  =  require('express');

var  jwt  =  require('express-jwt')({ secret:  config.secret });

var  router  =  express.Router();

var  pageService  =  require('services/page.service');

  

// routes

router.get('/', getAll);

router.get('/slug/:slug', getBySlug);

router.get('/:_id', jwt, getById);

router.post('/', jwt, create);

router.put('/:_id', jwt, update);

router.delete('/:_id', jwt, _delete);

  

module.exports  =  router;

  

function  getAll(req, res) {

	pageService.getAll()

		.then(function (pages) {

			// if admin user is logged in return all pages, otherwise return only published pages

			if (req.session.token) {

				res.send(pages);

			} else {

				res.send(_.filter(pages, { 'publish':  true }));

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getBySlug(req, res) {

	pageService.getBySlug(req.params.slug)

		.then(function (page) {

			// return page if it's published or the admin is logged in

			if (page.publish  ||  req.session.token) {

				res.send(page);

			} else {

				res.status(404).send('Not found');

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getById(req, res) {

	pageService.getById(req.params._id)

		.then(function (page) {

			res.send(page);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

	}

  

function  create(req, res) {

	pageService.create(req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  update(req, res) {

	pageService.update(req.params._id, req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  _delete(req, res) {

	pageService.delete(req.params._id)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}
```

`var  jwt  =  require('express-jwt')({ secret:  config.secret });` will import the `jsonwebtoken` module and the secret token required for the authentication.

We set routes for all the page operations, the ones with `jwt` appearing before its callback function will require authentication before execution.

The first function `getAll()` will check if the user is logged in as admin, if that is true the function returns the list of all the created pages from the database.

If the condition is false the function returns the list of published pages only.

The `getBySlug()` function gets  a page that matches the provided slug, the function checks if the page requested has been published or the admin is logged in, if either returns true the page is sent back as a response else a `404` status is returned.

`create()` helps in the addition of a new page, it grabs the body of the request(page contents), if the operation is successful it returns a `200` OK status code.

`update()` will update the contents of an existing page, it gets the `id`and `body` of the requested page, upon successful operation it returns a `200` OK status code.

`_delete()` deletes an existing page by grabbing the page `id` and returning a `200` status code upon successful operation.


#### Posts Controller

Create a new file `posts.controller.js` in the `api` directory to handle operations for blog posts.

The code for the posts controller 

```
var  config  =  require('config.json');

var  _  =  require('lodash');

var  express  =  require('express');

var  jwt  =  require('express-jwt')({ secret:  config.secret });

var  router  =  express.Router();

var  postService  =  require('services/post.service');

  

// routes

router.get('/', getAll);

router.get('/:year/:month/:day/:slug', getByUrl);

router.get('/:_id', jwt, getById);

router.post('/', jwt, create);

router.put('/:_id', jwt, update);

router.delete('/:_id', jwt, _delete);

  

module.exports  =  router;

  

function  getAll(req, res) {

	postService.getAll()

		.then(function (posts) {

			// if admin user is logged in return all posts, otherwise return only published posts

			if (req.session.token) {

				res.send(posts);

			} else {

				res.send(_.filter(posts, { 'publish':  true }));

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getByUrl(req, res) {

	postService.getByUrl(req.params.year, req.params.month, req.params.day, req.params.slug)

		.then(function (post) {

			// return post if it's published or the admin is logged in

			if (post.publish  ||  req.session.token) {

			res.send(post);

			} else {

				res.status(404).send('Not found');

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getById(req, res) {

	postService.getById(req.params._id)

		.then(function (post) {

			res.send(post);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  create(req, res) {

	postService.create(req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  update(req, res) {

	postService.update(req.params._id, req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  _delete(req, res) {

	postService.delete(req.params._id)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}
```

This file also imports the `jsonwebtoken` module to handle authentication `var  jwt  =  require('express-jwt')({ secret:  config.secret });` just like it is with the pages controller module.

`getAll()` returns a list of all posts for logged in users(admin), if the user is not logged in it only returns the published posts.

`getByUrl()` returns a post matching the provided url. The url for each post in question includes the date and slug associated with the post.

`getById()` returns a post matching the provided post `id`.

`update()` edits and updates an existing post and returns a `200/OK` status code after successfully updating the post.

`_delete()` removes an existing post from the list of all available posts. It uses the `id` of the post contained in the request to identify the right post to delete.


#### Redirects Controller

There are instances in the application where users are redirected after completing an operation. 

The next block contains code that performs functions pertaining to the redirect controller.

Add a new file in the `api` folder `redirects.controller.js`

Code for the redirects file

```
var  config  =  require('config.json');

var  _  =  require('lodash');

var  express  =  require('express');

var  jwt  =  require('express-jwt')({ secret:  config.secret });

var  router  =  express.Router();

var  redirectService  =  require('services/redirect.service');

  

// routes

router.get('/', jwt, getAll);

router.get('/:_id', jwt, getById);

router.post('/', jwt, create);

router.put('/:_id', jwt, update);

router.delete('/:_id', jwt, _delete);

  

module.exports  =  router;

  

function  getAll(req, res) {

	redirectService.getAll()

		.then(function (redirects) {

			res.send(redirects);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getById(req, res) {

	redirectService.getById(req.params._id)

		.then(function (redirect) {

			res.send(redirect);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  create(req, res) {

	redirectService.create(req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  update(req, res) {

	redirectService.update(req.params._id, req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  _delete(req, res) {

	redirectService.delete(req.params._id)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}
```

All functions and operations in this file require authentication.

`getAll()` gets a list of all available redirects from the database and sends it as a response.

`getById` gets a single redirect matching the provided `id`from the request and sends it back as a response.

`create()` adds a new redirect and returns `200/OK` status code upon successful creation.

`update()` edits and updates an existing redirect. The function identifies the redirect to be updated by matching the `id` and `body` in the request to existing ones in the database.

`delete()` removes an existing redirect and returns a `200/OK` status code upon successful removal.


#### Users Controller

We are going to add a controller file to handle user operations and data. 

Create a file in the `api` directory, `users.controller.js`. Add the following code

```
var  config  =  require('config.json');

var  express  =  require('express');

var  jwt  =  require('express-jwt')({ secret:  config.secret });

var  router  =  express.Router();

var  userService  =  require('services/user.service');

  

// routes

router.post('/authenticate', authenticateUser);

router.get('/current', jwt, getCurrentUser);

router.get('/:_id', jwt, getById);

router.put('/:_id', jwt, updateUser);

router.delete('/:_id', jwt, deleteUser);

  

module.exports  =  router;

  

function  authenticateUser(req, res) {

	userService.authenticate(req.body.username, req.body.password)

		.then(function (token) {

			if (token) {

				// authentication successful

				res.send({ token:  token });

			} else {

				// authentication failed

				res.status(401).send('Username or password is incorrect');

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getCurrentUser(req, res) {

	userService.getById(req.user.sub)

		.then(function (user) {

			if (user) {

				res.send(user);

			} else {

				res.sendStatus(404);

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  getById(req, res) {

	userService.getById(req.params._id)

		.then(function (user) {

			if (user) {

				res.send(user);

			} else {

				res.sendStatus(404);

			}

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  updateUser(req, res) {

	var  userId  =  req.user.sub;

	if (req.params._id  !==  userId) {

		// can only update own account

		return  res.status(401).send('You can only update your own account');

	}

  

	userService.update(userId, req.body)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}

  

function  deleteUser(req, res) {

	var  userId  =  req.user.sub;

	if (req.params._id  !==  userId) {

		// can only delete own account

		return  res.status(401).send('You can only delete your own account');

	}

  

	userService.delete(userId)

		.then(function () {

			res.sendStatus(200);

		})

		.catch(function (err) {

			res.status(400).send(err);

		});

}
```
`authenticateUser()` requests for a username and a password. If both parameters match one existing in the database the function returns a secret token which will be supplied upon future requests for that session.

If the username or password is incorrect the function returns a `401` status and send a string alongside `'Username or password is incorrect'`.

`getCurrentUser()` requests for the details of the current online user and compares it with the details of users existing in the database. 

If  a user with the details exist then the operation is successful else the function returns a `404/Not Found Error` status.

  `getById()` request for the user account that matches the provided `id`, if the user exists in the database the function returns the user.

`updateUser()`  will help edit current user details and update it with new details.

The function requests the current user details and stores the value in a variable `userId`.

The function the checks the `id` from the HTTP request and compares it with the value of `userId`, if they don't match then it returns a `401` status with the string `'You can only update your own account'`.

If they do match `userService.update()` runs and it updates the account matching `userid` with new details provided in the request body.

`deleteUser()`  will help remove current user details from the database.

The function requests the current user details and stores the value in a variable `userId`.

The function the checks the `id` from the HTTP request and compares it with the value of `userId`, if they don't match then it returns a `401` status with the string `'You can only delete your own account'`.

If they do match `userService.delete()` runs and it removes the account matching `userid`from the database.

We have come to the end of this tutorial, in the next tutorial we will add all service modules required for communication with the database.

1.  [Building A Content Management System Using The MEAN Stack - 1 (Create Server, Config File and Helper Modules)](https://steemit.com/utopian-io/@gotgame/5b98i4-building-a-content-management-system-using-the-mean-stack-1-create-server-config-file-and-helper-modules)

2.   [Building A Content Management System Using The MEAN Stack - 2(Create Controller Modules 1)](https://steemit.com/utopian-io/@gotgame/building-a-content-management-system-using-the-mean-stack-1-create-controller-modules-1)

Proof Of Work Done
https://github.com/olatundeee/mean-cms
๐Ÿ‘  , , , , , , , , , , , , , , , , ,
properties (23)
authorgotgame
permlinkbuilding-a-content-management-system-using-the-mean-stack-2-create-controller-modules-1
categoryutopian-io
json_metadata{"community":"busy","app":"steemit/0.1","format":"markdown","tags":["utopian-io","tutorials","technology","busy","programming"],"links":["https://github.com/nodejs/node","https://github.com/cornflourblue/meanie","http://jasonwatmore.com/","https://nodejs.org/en/download/package-manager/","https://angular.io/","https://www.mongodb.com/","https://nodemailer.com/transports/sendmail/","https://steemit.com/utopian-io/@gotgame/5b98i4-building-a-content-management-system-using-the-mean-stack-1-create-server-config-file-and-helper-modules","https://steemit.com/utopian-io/@gotgame/building-a-content-management-system-using-the-mean-stack-1-create-controller-modules-1","https://github.com/olatundeee/mean-cms"]}
created2018-09-03 16:54:09
last_update2018-09-03 17:50:54
depth0
children6
last_payout2018-09-10 16:54:09
cashout_time1969-12-31 23:59:59
total_payout_value15.807 HBD
curator_payout_value4.711 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length17,327
author_reputation23,969,707,386,372
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,203,468
net_rshares17,612,607,204,288
author_curate_reward""
vote details (18)
@ilovecoding ·
Hello! Your post has been resteemed and upvoted by @ilovecoding because **we love coding**! Keep up good work! Consider upvoting this comment to support the @ilovecoding and increase your future rewards! ^_^ Steem On! 
 ![](https://codingforspeed.com/images/i-love-coding.jpg) 
*Reply !stop to disable the comment. Thanks!*
๐Ÿ‘  , ,
properties (23)
authorilovecoding
permlink20180903t165424414z
categoryutopian-io
json_metadata{"tags":["ilovecoding"],"app":"ilovecoding"}
created2018-09-03 16:54:24
last_update2018-09-03 16:54:24
depth1
children0
last_payout2018-09-10 16:54:24
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length323
author_reputation40,845,997,808
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,203,485
net_rshares12,391,739,176
author_curate_reward""
vote details (3)
@portugalcoin ·
$7.61
Thank you for your contribution.
After analyzing your tutorial we suggest the following:

- Your code has enough spaces between each line, making it difficult to read and understand the code. Ident your code.

Looking forward to your upcoming tutorials.


Your contribution has been evaluated according to [Utopian policies and guidelines](https://join.utopian.io/guidelines), as well as a predefined set of questions pertaining to the category.
https://review.utopian.io/#modal1
To view those questions and the relevant answers related to your post, [click here](https://review.utopian.io/result/8/21114343).

---- 
Need help? Write a ticket on https://support.utopian.io/. 
Chat with us on [Discord](https://discord.gg/uTyJkNm). 
[[utopian-moderator]](https://join.utopian.io/)
๐Ÿ‘  , , , , , , , , , , ,
properties (23)
authorportugalcoin
permlinkre-gotgame-building-a-content-management-system-using-the-mean-stack-2-create-controller-modules-1-20180904t172030853z
categoryutopian-io
json_metadata{"tags":["utopian-io"],"links":["https://join.utopian.io/guidelines","https://review.utopian.io/#modal1","https://review.utopian.io/result/8/21114343","https://support.utopian.io/","https://discord.gg/uTyJkNm","https://join.utopian.io/"],"app":"steemit/0.1"}
created2018-09-04 17:20:33
last_update2018-09-04 17:20:33
depth1
children1
last_payout2018-09-11 17:20:33
cashout_time1969-12-31 23:59:59
total_payout_value5.753 HBD
curator_payout_value1.854 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length779
author_reputation599,460,589,822,571
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,312,389
net_rshares6,654,913,832,212
author_curate_reward""
vote details (12)
@utopian-io ·
Thank you for your review, @portugalcoin!

So far this week you've reviewed 16 contributions. Keep up the good work!
properties (22)
authorutopian-io
permlinkre-re-gotgame-building-a-content-management-system-using-the-mean-stack-2-create-controller-modules-1-20180904t172030853z-20180908t184210z
categoryutopian-io
json_metadata"{"app": "beem/0.19.42"}"
created2018-09-08 18:42:12
last_update2018-09-08 18:42:12
depth2
children0
last_payout2018-09-15 18:42:12
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length116
author_reputation152,955,367,999,756
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,723,174
net_rshares0
@steem-ua ·
#### Hi @gotgame!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
**Feel free to join our [@steem-ua Discord server](https://discord.gg/KpBNYGz)**
๐Ÿ‘  
properties (23)
authorsteem-ua
permlinkre-building-a-content-management-system-using-the-mean-stack-2-create-controller-modules-1-20180904t180226z
categoryutopian-io
json_metadata"{"app": "beem/0.19.54"}"
created2018-09-04 18:02:27
last_update2018-09-04 18:02:27
depth1
children0
last_payout2018-09-11 18:02:27
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length286
author_reputation23,214,230,978,060
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,315,727
net_rshares11,659,700,638
author_curate_reward""
vote details (1)
@steemitboard ·
Congratulations @gotgame! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

[![](https://steemitimages.com/70x80/http://steemitboard.com/notifications/votes.png)](http://steemitboard.com/@gotgame) Award for the number of upvotes

<sub>_Click on the badge to view your Board of Honor._</sub>
<sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub>



**Do not miss the last post from @steemitboard:**
<table><tr><td><a href="https://steemit.com/steemfest/@steemitboard/steemfest-steemitboard-support-the-travel-reimbursement-fund"><img src="https://steemitimages.com/64x128/https://cdn.steemitimages.com/DQmawPYDAwfrQM8YU6ejD1f87g64cvsmEFn8RQKHJMs4zxg/image.png"></a></td><td><a href="https://steemit.com/steemfest/@steemitboard/steemfest-steemitboard-support-the-travel-reimbursement-fund">SteemFestยณ - SteemitBoard support the Travel Reimbursement Fund.</a></td></tr></table>

> Support [SteemitBoard's project](https://steemit.com/@steemitboard)! **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
properties (22)
authorsteemitboard
permlinksteemitboard-notify-gotgame-20180906t173344000z
categoryutopian-io
json_metadata{"image":["https://steemitboard.com/img/notify.png"]}
created2018-09-06 17:33:42
last_update2018-09-06 17:33:42
depth1
children0
last_payout2018-09-13 17:33:42
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length1,200
author_reputation38,975,615,169,260
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,526,254
net_rshares0
@utopian-io ·
Hey, @gotgame!

**Thanks for contributing on Utopian**.
Weโ€™re already looking forward to your next contribution!

**Get higher incentives and support Utopian.io!**
 Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via [SteemPlus](https://chrome.google.com/webstore/detail/steemplus/mjbkjgcplmaneajhcbegoffkedeankaj?hl=en) or [Steeditor](https://steeditor.app)).

**Want to chat? Join us on Discord https://discord.gg/h52nFrV.**

<a href='https://steemconnect.com/sign/account-witness-vote?witness=utopian-io&approve=1'>Vote for Utopian Witness!</a>
๐Ÿ‘  
properties (23)
authorutopian-io
permlinkre-building-a-content-management-system-using-the-mean-stack-2-create-controller-modules-1-20180904t184037z
categoryutopian-io
json_metadata"{"app": "beem/0.19.42"}"
created2018-09-04 18:40:36
last_update2018-09-04 18:40:36
depth1
children0
last_payout2018-09-11 18:40:36
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length589
author_reputation152,955,367,999,756
root_title"Building A Content Management System Using The MEAN Stack - 3 (Create Controller Modules 2)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,318,609
net_rshares11,418,048,811
author_curate_reward""
vote details (1)