create account

Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules) by gotgame

View this thread on: hive.blogpeakd.comecency.com
· @gotgame · (edited)
$11.97
Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules)
### 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 fourth tutorial in the series of tutorials on building a content management system using the MEAN technology.

In the first three tutorials we created the backend server plus all helper and controller modules for the application.

In this tutorial we are going to work on creating the database services for the application.

We will create the following service modules in this tutorial

1. Page Service
2. Post Service
3. Redirect Service
4. User Service


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

In the server directory create a new folder `services` which will contain all service modules for this application.

#### Page Service 

In the created `services` folder add a new file `page.service.js` which will serve as the service module for the page controller module.

In the file we have 

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

var  _  =  require('lodash');

var  Q  =  require('q');

var  slugify  =  require('helpers/slugify');

var  mongo  =  require('mongoskin');

var  db  =  mongo.db(config.connectionString, { native_parser:  true });

db.bind('pages');

  

var  service  = {};

service.getAll  =  getAll;

service.getBySlug  =  getBySlug;

service.getById  =  getById;

service.create  =  create;

service.update  =  update;

service.delete  =  _delete;


module.exports  =  service;
  

function  getAll() {

	var  deferred  =  Q.defer();
	
	db.pages.find().toArray(function (err, pages) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		pages  =  _.sortBy(pages, function (p) { return  p.title.toLowerCase(); });

		deferred.resolve(pages);
	});
	
	return  deferred.promise;

}


function  getBySlug(slug) {

	var  deferred  =  Q.defer();

	db.pages.findOne({

		slug:  slug

	}, function (err, page) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		deferred.resolve(page);

	});

	return  deferred.promise;

}

function  getById(_id) {

	var  deferred  =  Q.defer();

	db.pages.findById(_id, function (err, page) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		deferred.resolve(page);

	});

	return  deferred.promise;

}


function  create(pageParam) {

	var  deferred  =  Q.defer();

	// generate slug from title if empty

	pageParam.slug  =  pageParam.slug  ||  slugify(pageParam.title);

	db.pages.insert(

		pageParam,

		function (err, doc) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

	return  deferred.promise;

}


function  update(_id, pageParam) {

	var  deferred  =  Q.defer();

	// generate slug from title if empty

	pageParam.slug  =  pageParam.slug  ||  slugify(pageParam.title);

	// fields to update

	var  set  =  _.omit(pageParam, '_id');

	db.pages.update(

		{ _id:  mongo.helper.toObjectID(_id) },

		{ $set:  set },

		function (err, doc) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

	return  deferred.promise;

}


function  _delete(_id) {

	var  deferred  =  Q.defer();

	db.pages.remove(

		{ _id:  mongo.helper.toObjectID(_id) },

		function (err) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

	return  deferred.promise;

}
```

This file uses the `q` library which is a promise module for JavaScript to handle promises.

 The line`mongo.db(config.connectionString, { native_parser:  true });` is used to connect to the MongoDB database server.

`db.bind(pages)` binds the service to the pages table in the database.

`service` creates a new object which holds all the methods required for this module as its properties.

`getAll()` accesses the pages table in the database and finds a list of all available page stored in the database then proceed to store it as an array.

`getBySlug()` accesses the pages table in the database and looks for one page from the list whose name matches the slug provided.

`getById(_id)` will look for the page matching the provided `id` in the pages table from the database.

`create()` generates a slug from the provided page title and uses that along with other parameters to create a new page and adds all values related to the newly created page to the database.

`update()` generates a slug from the provided page title then proceed to exclude fields from the database that does not require updating by editing the existing post field to add new values. 

The function then insert the set values into the provided database fields.

`_delete()` removes an entire page field including the contents of the page from the database.


#### Post Service

Create another file in the `services` directory, `post.service.js`. This file will handle all service operations the database relating to blog posts.

The code for this file 

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

var  _  =  require('lodash');

var  Q  =  require('q');

var  slugify  =  require('helpers/slugify');

var  mongo  =  require('mongoskin');

var  db  =  mongo.db(config.connectionString, { native_parser:  true });

db.bind('posts');

  

var  service  = {};

  

service.getAll  =  getAll;

service.getByUrl  =  getByUrl;

service.getById  =  getById;

service.create  =  create;

service.update  =  update;

service.delete  =  _delete;

  

module.exports  =  service;

  

function  getAll() {

	var  deferred  =  Q.defer();

	db.posts.find().sort({ publishDate:  -1 }).toArray(function (err, posts) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		deferred.resolve(posts);

	});

	return  deferred.promise;

}


function  getByUrl(year, month, day, slug) {

	var  deferred  =  Q.defer();

	db.posts.findOne({

		publishDate:  year  +  '-'  +  month  +  '-'  +  day,

		slug:  slug

	}, function (err, post) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		  deferred.resolve(post);

	});

	return  deferred.promise;

}

  
function  getById(_id) {

	var  deferred  =  Q.defer();

	db.posts.findById(_id, function (err, post) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

        deferred.resolve(post);

	});

	return  deferred.promise;

}


function  create(postParam) {

	var  deferred  =  Q.defer();

	// generate slug from title if empty

	postParam.slug  =  postParam.slug  ||  slugify(postParam.title);

    db.posts.insert(

		postParam,

		function (err, doc) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

	});

	return  deferred.promise;

}


function  update(_id, postParam) {

	var  deferred  =  Q.defer();

	// generate slug from title if empty

	postParam.slug  =  postParam.slug  ||  slugify(postParam.title);

	// fields to update

	var  set  =  _.omit(postParam, '_id');

	db.posts.update(

		{ _id:  mongo.helper.toObjectID(_id) },

		{ $set:  set },

		function (err, doc) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

		return  deferred.promise;

}

  

function  _delete(_id) {

	var  deferred  =  Q.defer();

	db.posts.remove(

		{ _id:  mongo.helper.toObjectID(_id) },

		function (err) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

	});

	return  deferred.promise;

}
```

`getAll()` looks through the posts table in the database to find all available posts, stores it in and stores all of the returned posts in an array.

`getByUrl()` looks through the posts in the database and finds the one post matching the the provided URL which is a combination of the publish date for the post and the slug associated with the post.

`getById()` looks the posts table in the database and finds the post matching the provided id.

`create()`  generates a slug from the provided post title and uses that along with other parameters to create a new post and adds all values related to the newly created post to the database.

`update()`  generates a slug from the provided post title then proceed to exclude fields from the database that does not require updating. 

The function then insert the set values into the provided database fields by editing the existing post field to add new values.

`_delete()` removes an entire page field including the contents of the page from the database.


#### Redirect Service 

Create a new file in the services directory `redirect.service.js`. It will handle all database communications for redirect operations in our application.

The code for the redirect service

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

var  _  =  require('lodash');

var  Q  =  require('q');

var  mongo  =  require('mongoskin');

var  db  =  mongo.db(config.connectionString, { native_parser:  true });

db.bind('redirects');

  

var  service  = {};

  

service.getAll  =  getAll;

service.getById  =  getById;

service.getByFrom  =  getByFrom;

service.create  =  create;

service.update  =  update;

service.delete  =  _delete;

  

module.exports  =  service;

  
function  getAll() {

	var  deferred  =  Q.defer();
	
	db.redirects.find().toArray(function (err, redirects) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		deferred.resolve(redirects);

	});

	return  deferred.promise;

}

  
function  getById(_id) {

	var  deferred  =  Q.defer();

	db.redirects.findById(_id, function (err, redirect) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		deferred.resolve(redirect);

	});

	return  deferred.promise;

}

  
function  getByFrom(from) {

	var  deferred  =  Q.defer();

	db.redirects.findOne({

		from:  from

	}, function (err, redirect) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		deferred.resolve(redirect);

	});

	return  deferred.promise;

}

  
function  create(redirectParam) {

	var  deferred  =  Q.defer();

	// validate

	var  errors  = [];

	if (!redirectParam.from) { errors.push('From is required'); }

	if (!redirectParam.to) { errors.push('To is required'); }

	if (!errors.length) {

		// ensure to and from are lowercase

		redirectParam.from  =  redirectParam.from.toLowerCase();

		redirectParam.to  =  redirectParam.to.toLowerCase();

		db.redirects.insert(

			redirectParam,

			function (err, doc) {

				if (err) deferred.reject(err.name  +  ': '  +  err.message);

				deferred.resolve();

			});

	} else {

		deferred.reject(errors.join('\r\n'));

	}

	return  deferred.promise;

}

  

function  update(_id, redirectParam) {

	var  deferred  =  Q.defer();

	// validate

	var  errors  = [];

	if (!redirectParam.from) { errors.push('From is required'); }

	if (!redirectParam.to) { errors.push('To is required'); }

	if (!errors.length) {

		// ensure to and from are lowercase

		redirectParam.from  =  redirectParam.from.toLowerCase();

		redirectParam.to  =  redirectParam.to.toLowerCase();

		// fields to update

		var  set  =  _.omit(redirectParam, '_id');

		db.redirects.update(

		{ _id:  mongo.helper.toObjectID(_id) },

		{ $set:  set },

		function (err, doc) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

	} else {

		deferred.reject(errors.join('\r\n'));

	}

	return  deferred.promise;

}


function  _delete(_id) {

	var  deferred  =  Q.defer();

	db.redirects.remove(

		{ _id:  mongo.helper.toObjectID(_id) },

		function (err) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

	return  deferred.promise;

}
```

`getAll()` returns a list of all available redirects from the database and stores it in an array.

`getById()` returns the redirect matching the provided id from the database id.

`getByFrom()` returns the redirect that is a result of a specific page which is used as parameter for this function. 

The page that results in the redirect is passed at the initialization of the function and the page redirected is returned at the execution of the function.

`create()` will add a new redirect to complete some operation in the application. 

The function uses a parameter `redirectParam` which comes in form of an object.

The object has a number of properties including `from` which is the page the redirect originates from  and `to` which is the page the redirect will result in.


`update()` will edit the properties relating to each redirect. In the course of executing update the value of the page the redirect is coming from and the page it will result in can be edited and updated in the database.

`_delete()` will remove any existing redirect from the database.


#### User Service

Create a new file in the services directory `user.service.js`. It will handle all database communications for user operations in our application.

The code for the user service

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

var  _  =  require('lodash');

var  jwt  =  require('jsonwebtoken');

var  bcrypt  =  require('bcryptjs');

var  Q  =  require('q');

var  mongo  =  require('mongoskin');

var  db  =  mongo.db(config.connectionString, { native_parser:  true });

db.bind('users');

  

var  service  = {};

  

service.authenticate  =  authenticate;

service.getAll  =  getAll;

service.getById  =  getById;

service.create  =  create;

service.update  =  update;

service.delete  =  _delete;

  

module.exports  =  service;

  

function  authenticate(username, password) {

	var  deferred  =  Q.defer();

	db.users.findOne({ username:  username }, function (err, user) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		if (user  &&  bcrypt.compareSync(password, user.hash)) {

		// authentication successful

		deferred.resolve(jwt.sign({ sub:  user._id }, config.secret));

		} else {

		// authentication failed

			deferred.resolve();

		}

	});

	return  deferred.promise;

}


function  getAll() {

	var  deferred  =  Q.defer();

	db.users.find().toArray(function (err, users) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		// return users (without hashed passwords)

		users  =  _.map(users, function (user) {

			return  _.omit(user, 'hash');

		});
		
		deferred.resolve(users);

	});

	return  deferred.promise;

}

  

function  getById(_id) {

	var  deferred  =  Q.defer();

	db.users.findById(_id, function (err, user) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		if (user) {

			// return user (without hashed password)

			deferred.resolve(_.omit(user, 'hash'));

		} else {

			// user not found

			deferred.resolve();

		}

	});

	return  deferred.promise;

}

  

function  create(userParam) {

	var  deferred  =  Q.defer();

	// validation

	db.users.findOne(

		{ username:  userParam.username },

		function (err, user) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			if (user) {

				// username already exists

				deferred.reject('Username "'  +  userParam.username  +  '" is already taken');

			} else {

				createUser();

			}

		});
		
	function  createUser() {

		// set user object to userParam without the cleartext password

		var  user  =  _.omit(userParam, 'password');

		// add hashed password to user object

		user.hash  =  bcrypt.hashSync(userParam.password, 10);

		db.users.insert(

			user,

			function (err, doc) {

				if (err) deferred.reject(err.name  +  ': '  +  err.message);

				deferred.resolve();

			});

	}

	return  deferred.promise;

}

  

function  update(_id, userParam) {

	var  deferred  =  Q.defer();

	// validation

	db.users.findById(_id, function (err, user) {

		if (err) deferred.reject(err.name  +  ': '  +  err.message);

		if (user.username  !==  userParam.username) {

			// username has changed so check if the new username is already taken

			db.users.findOne(

				{ username:  userParam.username },

				function (err, user) {

					if (err) deferred.reject(err.name  +  ': '  +  err.message);

					if (user) {

						// username already exists

						deferred.reject('Username "'  +  req.body.username  +  '" is already taken')

					} else {

						updateUser();

					}

				});

		} else {

			updateUser();

		}

	});

	function  updateUser() {

		// fields to update

		var  set  = {

			username:  userParam.username,

		};

		// update password if it was entered

		if (userParam.password) {

			set.hash  =  bcrypt.hashSync(userParam.password, 10);

		}

		db.users.update(

			{ _id:  mongo.helper.toObjectID(_id) },

			{ $set:  set },

			function (err, doc) {

				if (err) deferred.reject(err.name  +  ': '  +  err.message);

				deferred.resolve();

			});

	}

	return  deferred.promise;

}

  

function  _delete(_id) {

	var  deferred  =  Q.defer();

	db.users.remove(

		{ _id:  mongo.helper.toObjectID(_id) },

		function (err) {

			if (err) deferred.reject(err.name  +  ': '  +  err.message);

			deferred.resolve();

		});

	return  deferred.promise;

}
```

`authenticate()` will verify the a user in the database by comparing the provided the username and password with the ones in the database to see if there's a match with one of the usernames and password.

`getAll()` finds and returns a list of all available users from the database and stores the list in an array.

`getById()` finds a user using a provided id and returns the user details for the user if his data is found.

`create()` will add a new user to the database using the parameters provided at the initialization of the function.

Each newly created user has a username and during creation the function checks the database to see if that same username has not been used by another user.

If the provided username has not been used before the function then creates a new user by running the `createUser()` function which inserts the new user details to the database.

`update()` uses the id provided to locate the user details which will be edited with new values in the database.

If the username provided matches a username in the database the function proceeds to make the necessary edits. 

In the process of editing if the username provided does not match an existing username in the database the function `updateUser()` runs which will update all the values provided to the specified tables in the database.

`_delete()` will remove a specified user field with matching id as the one passed to the function.

### Curriculum

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)

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

Proof Of Work Done  
[https://github.com/olatundeee/mean-cms](https://github.com/olatundeee/mean-cms)
πŸ‘  , , , , , , , , , , , , , , , , , , , , , , , ,
properties (23)
authorgotgame
permlinkbuilding-a-content-management-system-using-the-mean-stack-3-create-services-modules
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://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://steemit.com/utopian-io/@gotgame/building-a-content-management-system-using-the-mean-stack-2-create-controller-modules-1","https://github.com/olatundeee/mean-cms"]}
created2018-09-09 17:52:42
last_update2018-09-09 17:55:00
depth0
children6
last_payout2018-09-16 17:52:42
cashout_time1969-12-31 23:59:59
total_payout_value9.268 HBD
curator_payout_value2.698 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length19,576
author_reputation23,969,707,386,372
root_title"Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,810,105
net_rshares11,289,409,714,603
author_curate_reward""
vote details (25)
@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
permlink20180909t175254420z
categoryutopian-io
json_metadata{"tags":["ilovecoding"],"app":"ilovecoding"}
created2018-09-09 17:52:54
last_update2018-09-09 17:52:54
depth1
children0
last_payout2018-09-16 17:52:54
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 - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,810,120
net_rshares490,957,937
author_curate_reward""
vote details (1)
@portugalcoin ·
$8.64
Thank you for your contribution.

- We suggest that you remove the spaces between the lines of code. Your code formatted this way is hard to read and looks very long.

- Put some pictures of your application. So we can see the progress.

I hope in the next tutorial follow our advice. Good job!

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.

To view those questions and the relevant answers related to your post, [click here](https://review.utopian.io/result/8/31314334).

---- 
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-3-create-services-modules-20180909t222922975z
categoryutopian-io
json_metadata{"tags":["utopian-io"],"links":["https://join.utopian.io/guidelines","https://review.utopian.io/result/8/31314334","https://support.utopian.io/","https://discord.gg/uTyJkNm","https://join.utopian.io/"],"app":"steemit/0.1"}
created2018-09-09 22:29:21
last_update2018-09-09 22:29:21
depth1
children0
last_payout2018-09-16 22:29:21
cashout_time1969-12-31 23:59:59
total_payout_value6.528 HBD
curator_payout_value2.108 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length786
author_reputation599,460,335,323,040
root_title"Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,826,578
net_rshares8,104,871,658,283
author_curate_reward""
vote details (10)
@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 (22)
authorsteem-ua
permlinkre-building-a-content-management-system-using-the-mean-stack-3-create-services-modules-20180909t224710z
categoryutopian-io
json_metadata"{"app": "beem/0.19.54"}"
created2018-09-09 22:47:09
last_update2018-09-09 22:47:09
depth1
children0
last_payout2018-09-16 22:47:09
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 - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id70,827,480
net_rshares0
@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>



> 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-20180914t071432000z
categoryutopian-io
json_metadata{"image":["https://steemitboard.com/img/notify.png"]}
created2018-09-14 07:14:30
last_update2018-09-14 07:14:30
depth1
children0
last_payout2018-09-21 07:14:30
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_length672
author_reputation38,975,615,169,260
root_title"Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id71,250,071
net_rshares0
@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>



> 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-20180925t135419000z
categoryutopian-io
json_metadata{"image":["https://steemitboard.com/img/notify.png"]}
created2018-09-25 13:54:18
last_update2018-09-25 13:54:18
depth1
children0
last_payout2018-10-02 13:54:18
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_length672
author_reputation38,975,615,169,260
root_title"Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id72,232,526
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 (22)
authorutopian-io
permlinkre-building-a-content-management-system-using-the-mean-stack-3-create-services-modules-20180913t122541z
categoryutopian-io
json_metadata"{"app": "beem/0.19.42"}"
created2018-09-13 12:25:42
last_update2018-09-13 12:25:42
depth1
children0
last_payout2018-09-20 12:25: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_length589
author_reputation152,955,367,999,756
root_title"Building A Content Management System Using The MEAN Stack - 4 (Create Services Modules)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id71,173,225
net_rshares0