2
\$\begingroup\$

I am creating a REST API to access a database of users. I am new to Node.js and developing REST APIs in general. I am also trying to use best security practices.

main.js

var fs = require('fs');
var restify = require('restify');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');

mongoose.connect('localhost', 'nodejs-sample');

var User = require('./models/user')

// SSL options
var options = {
  certificate: fs.readFileSync('./ssl/cert.pem'),
  key: fs.readFileSync('./ssl/key.pem')
}

var server = restify.createServer(options);

server.use(bodyParser.urlencoded({extended: true}));
server.use(bodyParser.json());

server.get('/users', function(req, res) {
  User.find(function(err, users) {
    if (err) {
      res.send(err);
    }

    res.json(users);
  });
});

server.post('/users', function(req, res) {
  bcrypt.hash(req.body.password, 10, function(err, hash) {
    if (err) {
      res.send(err);
    }

    User.create({
      username: req.body.username,
      first_name: req.body.first_name,
      last_name: req.body.last_name,
      email: req.body.email,
      hash: hash
    }, function(err) {
      if (err) {
        res.send(err)
      }

      res.json({message: 'User added'});
    });
  });
});

server.get('/users/:user_id', function(req, res) {
  User.findById(req.params.user_id, function(err, user) {
    if (err) {
      res.send(err);
    }

    res.json(user);
  });
});

server.put('/users/:user_id', function(req, res) {
  var body = req.body;
  if (body.password) {
    bcrypt.hash(body.password, 10, function(err, hash) {
      if (err) {
        res.send(err);
      }

      delete body.password;
      body.hash = hash;
      User.update({_id: req.params.user_id}, body, function() {
        res.json({message: 'User updated'});
      });
    });
  } else {
    User.update({_id: req.params.user_id}, body, function() {
      res.json({message: 'User updated'});
    });
  }
});

server.del('/users/:user_id', function(req, res) {
  User.findByIdAndRemove(req.params.user_id, function(err) {
    if (err) {
      res.send(err);
    }

    res.json({message: 'User deleted'});
  });
});

server.listen(process.env.PORT || 8080, function() {
  console.log('%s listening at %s', server.name, server.url);
});

models/user.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var UserSchema = new Schema({
  username: {
    type: String,
    required: true,
    unique: true
  },
  first_name: {
    type: String,
    required: true
  },
  last_name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  hash: {
    type: String,
    required: true
  }
});

// remove hash from JSON output
UserSchema.methods.toJSON = function() {
  var obj = this.toObject();
  delete obj.hash;
  return obj;
};

UserSchema.methods.verifyPassword = function(password, cb) {
  bcrypt.compare(password, this.hash, function(err, res) {
    if (err) {
      return cb(err);
    }

    cb(null, res);
  });
};

module.exports = mongoose.model('User', UserSchema);
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Few points to consider:
- Extract users CRUD logic to UsersService - this service will interact with mongoose and will be responsible for create, get, update and delete operations.
- Consider using Json Web Tokens instead of passing the password for every put request - it is an alternative for using sessions.

Overall for a newbie I consider this as a very good code.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.