Express mongoDB Integration testing for private/secured routes - mongodb

I am trying to run a integration test for one of the express routes in the application.
The routed is a protected route allows user to create supplier when user is authenticated.
I am trying to login user before making a request to the 'api/v1/supplier' (protected route) route but not able to login user before calling the Login API give 500 error back, the Login API is working as expected when tested separately.
Here is the test that I am trying. request help!
process.env.NODE_ENV = 'development';
const expect = require('chai').expect;
const request = require('supertest');
const app = require('../../../app.js');
const conn = require('../../../db/index.js');
describe('POST /api/v1/supplier ', () => {
let token = '';
before(done => {
conn
.connect()
.then(done())
.catch(err => done(err));
});
after(done => {
conn
.close()
.then(done())
.catch(err => done(err));
});
it('Error, on unauthorized POST Supplier request', done => {
request(app)
.post('/api/v1/users/login')
.send({ email: 'sgrmhdk00#gmail.com', password: '12345678' })
.end(function(err, res) {
token = res.body.token;
});
request(app)
.post('/api/v1/supplier')
.set('Authorization', 'Bearer' + token)
.send({ supplierID: '1234567' })
.then(res => {
const body = res.body;
expect(body).to.contain.property('status');
expect(body).to.contain.property('error');
done();
})
.catch(err => done(err));
});
});
db/index.js
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const DB_URI = 'mongodb://localhost:27017/myapp';
function connect() {
return new Promise((resolve, reject) => {
dotenv.config({ path: './config.env' });
const setDatabase = () => {
if (process.env.NODE_ENV === 'development') {
const DB = process.env.DATABASE;
return DB;
} else {
const DB = process.env.DATABASE_PRODUCTION.replace(
'<PASSWORD>',
process.env.DATABASE_PASSWORD
);
return DB;
}
};
const DB = setDatabase();
mongoose
.connect(DB, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false
})
.then(() => console.log('DB connection successful!'));
});
}
function close() {
return mongoose.disconnect();
}
module.exports = { connect, close };

You need to call you API with token, but the two calls are asynchronous, you need call the second method inside the end of the first:
it('Error, on unauthorized POST Supplier request', done => {
request(app)
.post('/api/v1/users/login')
.send({ email: 'sgrmhdk00#gmail.com', password: '12345678' })
.end(function(err, res) {
if(err){
done(err)
return
}
token = res.body.token;
request(app)
.post('/api/v1/supplier')
.set('Authorization', 'Bearer' + token)
.send({ supplierID: '1234567' })
.then(res => {
const body = res.body;
expect(body).to.contain.property('status');
expect(body).to.contain.property('error');
done();
})
.catch(err => done(err));
});
});

Related

How to make POST request using MongoDB?

I'm trying to make a POST request to my database. However, when I use Postman to test if the request is being made, it's giving me back an error,
Cannot POST /api/grocery
I'm using Model, View, Controller for my project. This is my index file
const express = require('express')
const app = express()
const port = 3000
const groceryController = require('./Controller/controllerGrocery.js')
app.use(express.urlencoded({extended: true}));
app.post('api/grocery', (req, res) => {
groceryController.addGrocery(req, res)
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
This is my controller file
const models = require('../Model/modelGrocery.js')
const addGrocery = (req, res) => {
const addGrocery = (err) => {
if (err) {
res.status(500).send()
} else {
res.status(201).end();
}
}
models.addGrocery(req.body, addGrocery)
}
module.exports = {
addGrocery: addGrocery
}
This is my model file that I'm connecting to the database
var db = require('../../DB/db.js');
const getGrocery = (doNext) => {
//query the database
db.find()
.then(result => doNext(null, result))
.catch(err => doNext(err))
//callback
}
const addGrocery = (grocery, callback) => {
db.insertOne({
item: grocery.item,
quantity: grocery.quantity
})
.catch(err => callback(err))
}
module.exports = {
addGrocery: addGrocery
}
Change API Path from api/grocery to /api/grocery
app.post('/api/grocery', (req, res) => {
groceryController.addGrocery(req, res)
})

"No current user" from currentSession() AWS Amplify and Cognito

I am trying to get a REST API to return currentSession() from AWS Amplify and Cognito. The SignIn function works and i get a CognitoUser object returned, however, the getSession() function returns "No current user"
const Amplify = require('aws-amplify');
const express = require('express');
const router = express.Router();
Amplify.default.configure({
Auth: {
region: 'REGION',
userPoolId: 'USERPOOLID',
userPoolWebClientId: 'WEBCLIENTID',
authenticationFlowType: 'AUTHTYPE',
}
})
router.post('/', (req, res) => {
async function signIn(username, password) {
try {
Amplify.Auth.signIn(username, password)
.then(() => getSession())
.catch(err => console.log(err));
} catch (error) {
res.json(error);
}
}
async function getSession() {
try {
Amplify.Auth.currentSession()
.then(data => console.log(data))
.catch(err => console.log(err));
} catch (error) {
res.json('error');
}
}
signIn(req.body.u, req.body.p);
});
Help!

req.session.user gives 'undifined' as output

I am implementing a login authentication program in MERN stack.
When I enter correct user name and password, login function works fine.
There are some components which can be displayed only if the client is logged in. Therefore, to validate the client I have implemented authenticator function in the server which should return success message along with the session object.
Once I try to authenticate, req.session.user gives the output as 'undefined'. I referred several similar questions but couldn't solve my issue.How can I solve this issue?
Login function,
router.post('/login', (req, res) => {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return res.status(400).json({ msg: "Please enter all fields" });
}
//Find user
User.findOne({ email : email })
.then(user => {
if(!user){
console.log('Not a user')
}
//Password matching
bcrypt.compare(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch){
console.log('Logged in')
const userSession = {
id: user.id,
name : user.name,
email : user.email
};
req.session.user = userSession;
res.json({ msg: "Logged in successfully", userSession});
} else {
console.log('Incorrect username or password')
}
});
})
.catch(err => console.log(err));
});
server.js,
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
const cors = require('cors');
const MongoDBStore = require('connect-mongodb-session')(session);
const app = express();
const router = express.Router();
const {IS_PROD} = require('./config/config');
const MAX_AGE = 1000 * 60 * 2;
mongoose.connect("mongodb+srv://root:admin#cluster0-ynman.gcp.mongodb.net/test?retryWrites=true&w=majority", {useNewUrlParser:true, useCreateIndex:true, useUnifiedTopology:true})
.then(() => console.log('Mongo DB Connected'))
.catch(err => console.log(err));
//setting up connect-mongodb-session store
const mongoDBStore = new MongoDBStore({
uri: "mongodb+srv://root:admin#cluster0-ynman.gcp.mongodb.net/test?retryWrites=true&w=majority",
collection : "mySession"
})
//Bodyparser
app.use(express.urlencoded({extended:false}));
app.use(cors());
app.use(express.json());
//Express Session
app.use(session({
name: 'session',
secret: 'secret',
resave: true,
saveUninitialized: false,
store : mongoDBStore,
cookie :{
path : '/',
httpOnly: false,
maxAge : MAX_AGE,
sameSite: false,
secure : IS_PROD
}
}));
//Routes
app.use('/', require('./routes/index'));
app.use('/users', require('./routes/users'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server starts on port ${PORT}`));
Authenticate funtion,
router.get("/authenticator", (req, res) => {
const userSession = req.session.user;
console.log(userSession);
if(userSession){
return res.json({msg : "Authenticated successfully", userSession});
} else {
return res.status(401).json({msg : "Unauthorized"});
}
});

Issues posting to my mongo database in react native

I am very new to React Native and I am trying to figure out how to connect my front end to my back end. I realize I may have my folder structure set up oddly but the connection works and I can fetch data from the database but when I attempt a post, it throws a 500 error. I cannot seem to figure out what is happening with it. If anyone has some insight I would greatly appreciate it. The post method console logs the req.body and "Here we are" in the controller file but fails immediately after that.
// index.js
require("dotenv").config();
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const morgan = require("morgan");
const { UserRoutes, TweetsRoutes } = require("./modules");
import dbConfig from "./config/db";
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(morgan("dev"));
// -----Database ----- \\
dbConfig(process.env.MONGO_DB_URL);
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use("/api", [UserRoutes, TweetsRoutes]);
// app.get("/", (req, res) => {
// res.send("endpoint live");
// });
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server listening on port ${PORT}🏄`));
// db.js
const mongoose = require("mongoose");
export default mongoURL => {
mongoose.Promise = global.Promise;
mongoose.connect(
mongoURL,
{ useNewUrlParser: true }
);
let db = mongoose.connection;
db.once("open", () => console.log("Connected to the database"));
db.on("error", console.error.bind(console, "Mongo connection error: "));
};
// tweetController.js
import Tweet from "./TweetsSchema";
module.exports = {
createTweet: async (req, res, next) => {
const createdTweet = req.body;
console.log("req.body: ", req.body);
try {
console.log("Here we are");
let tweet = await new Tweet.create(createdTweet);
tweet.save();
console.log("tweet: ", tweet);
res.status(201).json(tweet);
} catch (error) {
res.status(500).json({
error: true,
message: "There was an error creating the tweet"
});
}
},
getAllTweets: async (req, res, next) => {
const foundTweets = await Tweet.find({})
.lean()
.exec();
res.status(200).json(foundTweets);
next();
}
};
// actions.js
export const postTweet = tweet => {
let response = axios
.post(
`http://10.0.2.2:<PORT>/api/tweet`,
{ tweet },
{
headers: {
"Content-Type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin": "*"
}
}
)
.then(res => {
return res.data;
})
.catch(error => {
console.log(error);
});
return {
type: POST_TWEET,
payload: response
};
};
The problem is you mixed 2 commands for creating a new document
Instead of using both new and create like this:
let tweet = await new Tweet.create(createdTweet);
You should use only 1 of them like so:
let tweet = await Tweet.create(createdTweet);
tweet.save();
Or:
let tweet = new Tweet(createdTweet);
await tweet.save();

Passport: Error: passport.initialize() middleware not in use;

I'm have an express server with MongoDB and Mongoose, and using passport to authenticate with JWT, but getting an error as in the title.
I'm following the passport-jwt documentation, but am still getting the error. What am I doing wrong?
Here is the error message when doing GET call on localhost3090 with a valid JWT:
::1 - - [16/Mar/2018:05:35:47 +0000] "GET / HTTP/1.1" 500 1677 "-" "PostmanRuntime/7.1.1"
Error: passport.initialize() middleware not in use
at IncomingMessage.req.login.req.logIn (/Users/okadachikara/react-courses/projects/server/node_modules/passport/lib/http/request.js:46:34)
at JwtStrategy.strategy.success (/Users/okadachikara/react-courses/projects/server/node_modules/passport/lib/middleware/authenticate.js:248:13)
at verified (/Users/okadachikara/react-courses/projects/server/node_modules/passport-jwt/lib/strategy.js:115:41)
at /Users/okadachikara/react-courses/projects/server/services/passport.js:34:7
at /Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/model.js:3930:16
at _init (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/query.js:2007:5)
at model.Document.init (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/document.js:393:5)
at completeOne (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/query.js:1993:12)
at Immediate.<anonymous> (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/query.js:1520:11)
at Immediate._onImmediate (/Users/okadachikara/react-courses/projects/server/node_modules/mquery/lib/utils.js:119:16)
at runCallback (timers.js:773:18)
at tryOnImmediate (timers.js:734:5)
at processImmediate [as _immediateCallback] (timers.js:711:5)
My server/controllers/authentication.js:
const User = require('../models/user');
const jwt = require('jwt-simple');
const config = require('../config');
function tokenForUser(user) {
const timestamp = new Date().getTime();
return jwt.encode({ sub: user.id, iat: timestamp }, config.secret);
}
exports.signup = function (req, res, next) {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return res.status(422).send({ error: 'You must provide an email and
password' });
}
// see if user with the given email exists
User.findOne({ email: email }, function (err, existingUser) {
if (err) { return next(err); }
if (existingUser) {
return res.status(422).send({ error: 'A user with that email
already exists' });
}
const user = new User({
email: email,
password: password
});
user.save(function (err) {
if (err) { return next(err); }
res.json({ token: tokenForUser(user), iat: jwt.iat });
});
});
};
My server/services/passport.js
const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../models/user');
const config = require('../config');
const jwtOptions = {
jwtFromRequest: ExtractJwt.fromHeader('authorization'),
secretOrKey: config.secret
};
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);
My server/router.js
const passport = require('passport');
const Authentication = require('./controllers/authentication');
const passportService = require('./services/passport');
const requireAuth = passport.authenticate('jwt', { sesssion: false });
module.exports = function (app) {
app.get('/', requireAuth, function (req, res) {
res.send({ hi: 'there' });
});
app.post('/signup', Authentication.signup);
};
You need to initialize the passport module before using it:
let app = express();
app.use(passport.initialize());