1.0.0 • Published 4 years ago

tracking-location v1.0.0

Weekly downloads
1
License
MIT
Repository
-
Last release
4 years ago

Express Logo npm Build Status Coverage Status Gitter

BACK-END for tracking-app

Written by Vudang

I.Install Library

yarn init
yarn add bcrypt express jsonwebtoken 
mongodb mongoose ngrok nodemon

II.Project structures

    src
  |__ middlewares
  | |__ auth.js
  | |__ task.js
  | |__ ... (one reducer per file)
  | |__ index.js (root reducer) -> Use combineReducers here ^^
  |
  |__ models
  | |__ auth.js
  | |__ task.js
  | |__ ...
  |
  |__ routes
  | 
  |__ index.js (setup Store Provider) -> Wrap components here 

III.Database Setup

Make sure you installed MongoDB

  • MACOS
    https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/
  • Windows
    https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

    Make sure you create -dbpatch for MongoDB

    Make sure MongoDB is running

IV.Let's Go

Getting Started

1. Create endpoint (index.js)

const connectionString = 'mongodb://localhost/trackingDatabase'
const configOption = {
  useNewUrlParser: true,
  useUnifiedTopology: true
}

mongoose.connect(connectionString, configOption);

mongoose.connection.on('error', (err) => {
  console.log(err);
})

mongoose.connection.on('connected', () => {
  console.log('Mongoose connected successfully')
})

const app = express();
app.use(bodyParser.json());


app.listen(3000, () => {
  console.log('Server is running on port 3000')
})
```

2. Create our model

  • USER MODEL

    • The first we import 2 libraries : mongoose and bcrypt
    • Create UserSchema for Validation
    const mongoose = require('mongoose');
    const brcrypt = require('bcrypt');
    
    const UserSchema = new mongoose.Schema({
      email:{
        type:String,
        unique:true,
        required:true
      },
      password:{
        type:String,
        required:true
      }
    })
    
    // Hooks 
    /* 1.We get context of this Model (use declare function not use arrow function)
    * 2.Validation if user isModified (existing -> resolve done() )
    * 3.Else we call bcrypt function genSalt (valueSalt)
    * 4.Then we call hash function (hash password with salt value above)
    * 5.Finally we set user password to hash value
    * 6.We must define parameter done for resolve middlewares if we dont have request cant be done.
    *  */ 
    UserSchema.pre('save',function(done){
      const user = this;
      if(!user.isModified('password')) 
        return done();
      brcrypt.genSalt(10,(err,salt) => {
        if(err) 
          return done(err);
        brcrypt.hash(user.password,salt,(err,hash) => {
          if(err)
            return done(err);
          user.password = hash;
          done();
        });
      });
    });
    
    //Compare
    /**
    * 1.Add new property for UserSchema call it comparePassword
    * 2.Return new Promise with compare method of bcrypt
    * 3.Compare parameter password with hash value in out database
    */
    
    UserSchema.methods.comparePassword = function comparePassword(comparePassword){
      const user = this;
      return new Promise((resolve,reject) => {
        brcrypt.compare(comparePassword,user.password,(err,isMatchPassword) => {
          if(err)
            return reject(err)
          if(!isMatchPassword)
            return reject(false);
          resolve(true)
        })
      })
    }
    mongoose.model('User',UserSchema);
  • TRACK MODEL

    const mongoose = require('mongoose');
    // Point Schema save our coordinate
    const PointSchema = new mongoose.Schema({
      timstamp:Number,
      coors:{
        latitude:Number,
        longitude:Number,
        altitude:Number,
        accuracy:Number,
        heading:Number,
        spead:Number
      }
    });
    
    // Track Schema store our User with their locations
    const TrackSchema = new mongoose.Schema({
      _userID:{
        type:mongoose.Schema.Types.ObjectId,
        ref:'User'
      },
      trackName:{
        type:String,
        default:''
      },
      locations:[PointSchema]
    })
    mongoose.model('Track',TrackSchema);
  • Now,we have 2 models :

    • User model : describe user in our database.
    • Track model : describe location with user.

    3.Create our middlewares

  • We need to check JWT has been available from request header.If we have JWT we can access application,otherwise not.After resolve middlewares,we will send user information to client.

    const { response } = require('express');
    const jwt = require('jsonwebtoken');
    const mongoose = require('mongoose');
    const User = mongoose.model('User');
    
    const SECRET_KEY = 'YOUR_SECRET_KEY';
    const JWT_OPTIONS = {
      expiresIn:'7d'
    }
    
    const authenticationMiddleware =  (request,response,next) => {
      const {authorization} = request.headers;
      if(!authorization){
        return response.status(401).send({error:'You must have token'});
      }
    
      const token = authorization.replace('Bearer ','');
      
      jwt.verify(token,SECRET_KEY,JWT_OPTIONS,async (err,payload) => {
        if(err){
          return response.status(401).send({err:'You must have token'});
        }
        const {userID} = payload;
        const user  = await User.findById({_id:userID});
        request.user = user;
        next();
      })
    }
    
    module.exports = authenticationMiddleware;

    4. Create our routes

  • Authentication Router

    const mongoose = require('mongoose');
    const express = require('express');
    const jwt = require('jsonwebtoken');
    
    const router = express.Router();
    const User = mongoose.model('User');
    
    const SECRET_KEY = 'YOUR_SECRET_KEY';
    const JWT_OPTIONS = {
      expiresIn:'7d'
    }
    router.post('/register',async (request,response) => {
      const {email,password} = request.body;
      try{
        const user = new User({email:email,password:password});
        await user.save()
        const token = jwt.sign({userID:user._id},SECRET_KEY,JWT_OPTIONS)
        response.send({token})
      }
      catch(err){
        return response.status(422).send(err.message)
      } 
    })
    
    router.post('/login',async (request,response) => {
      const {email,password} = request.body;
      if(!email || !password){
        return response.status(422).send({error:'Youst must provide email and password'})
      }
      const user = await User.findOne({email});
      if(!user){
        return response.status(404).send({error:'Invalid email or password'})
      }
      try {
        await user.comparePassword(password);
        const token = jwt.sign({userID:user._id},SECRET_KEY,JWT_OPTIONS)
        response.send({token})
      }
      catch(err){
        return response.status(422).send({err:'Invalid password or email'})
      }
    })
    
    module.exports = router;
    • We create authentication router for our sever : /register and /login. They are using POST method, because we want to send email and password from request body to our server.
    • POST/Register : We are making async function that await User model create an instance and signup new JWT send it to client.
    • POST/Login : We are making async function that await our database find user.If we find,we also send it to client.comparePassword is a method we define in User model throught out Property.
  • Track Router

    const express =require('express');
    const mongoose = require('mongoose');
    const authenticationMiddleware = require('../middlewares/authMiddleware');
    const Track = mongoose.model('Track');
    const router = express.Router();
    router.use(authenticationMiddleware);
    
    router.get('/tracks',async (request,response) => {
      try {
        const track = await Track.find({_userID:request.user._id});
        response.send({track})
      }
      catch(err){
        response.status(404).send({error:'Dont find track'})
      }
    })
    
    router.post('/tracks',async (request,response) => {
      const {trackName,locations} = request.body;
      console.log(request.body)
      if(!trackName || !locations) 
        response.status(422)
        .send({error:'You must have track name and locations'})
      try {
        const newTrack = new Track({
          _userID:request.user._id,
          trackName,
          locations
        })
        await newTrack.save();
        response.send(newTrack)
      }
      catch(err) {
        response.status(422).send({error:err.message})
      }
    })
    module.exports = router;
    • We build 2 HTTP Methods:
      • 1.GET TRACKS: This method get all track with _userID provide in middlewares. So we must have router.use(authMiddleware)
      • 2.POST TRACKS: This method create a POST HTTP REQUEST to server and create newTrack,with trackName and locations were provided by request body,and _userID from middlewares.
    • So we can recognize the important of JWT in this Server.Many data,many information have been protected by JWT and we can use it too easy with Token.

Happy coding ^^