<repo_name>wesyoung9987/node-passport-boilerplate<file_sep>/controllers/client.js
const Client = require('../models/client');

exports.getPendingUserClients = function(req, res, next) {
  const userId = req.body.userId;
  const clientType = req.body.clientType;

  Client.find({ userId: userId, type: clientType, actualSalePrice: 0 }, (err, data) => {
    if (err) {
      return next(err);
    }

    res.json({ pendingClients: data });
  });
}
<file_sep>/services/passport.js
const passport = require('passport');
const User = require('../models/user');
const config = require('../config');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const LocalStrategy = require('passport-local');

// Using LocalStrategy for login

// Tell passport to use email instead of username
const localOptions = { usernameField: 'email' };
const localLogin = new LocalStrategy(localOptions, function(email, password, done) {
  User.findOne({ email: email }, function(err, user) {
    if (err) {
      return done(err);
    }

    if (!user) {
      return done(null, false);
    }

    user.comparePassword(password, function(err, isMatch) {
      if (err) {
        return done(err);
      }

      if (!isMatch) {
        return done(null, false);
      }

      // here passport will take user and assign it to req.user
      return done(null, user);
    });
  });
});

// Using JwtStrategy for authenticated requests

// tell passport to look for token on header called authorization
const jwtOptions = {
  jwtFromRequest: ExtractJwt.fromHeader('authorization'),
  secretOrKey: config.secret // the secret for passport to use in order to decode jwt
};

const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
  User.findById(payload.sub, function(err, user) {
    if (err) {
      return done(err, false);
    }

    if (user) {
      done(null, user);
    } else {
      done(null, false);
    }
  });
});

passport.use(jwtLogin);
passport.use(localLogin);
<file_sep>/models/leadGroup.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const leadGroupSchema = new Schema({
  userId: { type: Schema.Types.ObjectId, ref: 'user' },
  utcDateString: { type: String, required: true },
  contacts: {
    total: { type: Number, default: 0 },
    other: { type: Number, default: 0 },
    doorsKnocked: { type: Number, default: 0 },
    internet: { type: Number, default: 0 },
    sphere: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    },
    forSaleByOwner: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    },
    expiredListing: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    },
    areaProsp: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    }
  },
  followUps: {
    total: { type: Number, default: 0 },
    other: { type: Number, default: 0 },
    doorsKnocked: { type: Number, default: 0 },
    internet: { type: Number, default: 0 },
    sphere: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    },
    forSaleByOwner: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    },
    expiredListing: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    },
    areaProsp: {
      total: { type: Number, default: 0 },
      other: { type: Number, default: 0 },
      phone: { type: Number, default: 0 },
      text: { type: Number, default: 0 },
      email: { type: Number, default: 0 },
      social: { type: Number, default: 0 },
    }
  },
  setAppts: {
    total: { type: Number, default: 0 },
    buyer: { type: Number, default: 0 },
    seller: { type: Number, default: 0 }
  },
  heldAppts: {
    total: { type: Number, default: 0 },
    buyer: { type: Number, default: 0 },
    seller: { type: Number, default: 0 }
  },
  contractsSigned: {
    total: { type: Number, default: 0 },
    buyer: { type: Number, default: 0 },
    seller: { type: Number, default: 0 }
  },
  pendingClose: {
    total: { type: Number, default: 0 },
    buyer: [{ type: Schema.Types.ObjectId, ref: 'client' }],
    seller: [{ type: Schema.Types.ObjectId, ref: 'client' }]
  },
  closed: {
    total: { type: Number, default: 0 },
    buyer: [{ type: Schema.Types.ObjectId, ref: 'client' }],
    seller: [{ type: Schema.Types.ObjectId, ref: 'client' }]
  }
},
{
    timestamps: true
});

const ModelClass = mongoose.model('leadGroup', leadGroupSchema);

module.exports = ModelClass;
<file_sep>/controllers/authentication.js
const jwt = require('jwt-simple');
const User = require('../models/user');
const config = require('../config');

function tokenForUser(user) {
  const timestamp = new Date().getTime();
  return jwt.encode({ sub: user.id, iat: timestamp }, config.secret);
}

exports.signin = function(req, res, next) {
  // user was put onto req in passport localLogin
  res.send({ token: tokenForUser(req.user), userData: { id: req.user.id, firstName: req.user.firstName, email: req.user.email, role: req.user.role } });
}

exports.signup = function(req, res, next) {
  const email = req.body.email;
  const password = <PASSWORD>;
  const firstName = req.body.firstName;
  const lastName = req.body.lastName;
  const role = req.body.role;
  console.log(req.body);

  if (!firstName || !lastName) {
    return res.status(422).send({ error: 'First and last name are required.'});
  }

  if (!role) {
    return res.status(422).send({ error: 'User role must be specified.'} );
  }

  if (!email || !password) {
    return res.status(422).send({ error: 'Email and password required'});
  }

  User.findOne({ email: email }, function(err, existingUser) {
    if (err) {
      return next(err);
    }

    if (existingUser) {
      return res.status(422).send({ error: 'Email is in use' });
    }

    const user = new User({
      email: email,
      firstName: firstName,
      lastName: lastName,
      password: <PASSWORD>,
      role: role
    });

    user.save(function(err) {
      if (err) {
        return next(err);
      }

      res.json({ token: tokenForUser(user), userData: { id: user.id, firstName: user.firstName, email: user.email, role: user.role } });
    });

  });

}
<file_sep>/models/paymentDetails.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const paymentDetailsSchema = new Schema({
  clientId: { type: Schema.Types.ObjectId, ref: 'client' },
  stripeCustomer: { type: String, default: '' },
  stripePlan: { type: String, default: '' },
  stripeSubscription: { type: String, default: '' },
},
{
    timestamps: true
});

const ModelClass = mongoose.model('paymentDetails', paymentDetailsSchema);

module.exports = ModelClass;
<file_sep>/models/team.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const teamSchema = new Schema({
  name: { type: String, default: '' },
  allowedMembers: { type: Number, default: 1 },
  numberOfMembers: { type: Number, default: 1 },
},
{
    timestamps: true
});

const ModelClass = mongoose.model('team', teamSchema);

module.exports = ModelClass;
<file_sep>/router.js
const Authentication = require('./controllers/authentication');
const Lead = require('./controllers/lead');
const Client = require('./controllers/client');
const passportService = require('./services/passport');
const passport = require('passport');

// session false here tells passport to not create a
// cookie based session
const requireAuth = passport.authenticate('jwt', { session: false });
const requireSignin = passport.authenticate('local', { session: false });

module.exports = function(app) {
  app.get('/', requireAuth, function(req, res) {
    res.send({ message: 'Super secret code is ABC123' });
  });
  app.post('/signin', requireSignin, Authentication.signin);
  app.post('/signup', Authentication.signup);
  app.post('/get-lead-group-by-day', requireAuth, Lead.getLeadGroupByDay);
  app.post('/save-lead-group', requireAuth, Lead.saveLeadGroup);
  app.post('/save-pending-close', requireAuth, Lead.savePendingClose);
  app.post('/save-client-close', requireAuth, Lead.saveClientClose);
  app.post('/get-pending-user-clents', requireAuth, Client.getPendingUserClients);
}
