NodeJS module.exports does not work as expected - node.js

I am writing a web service in NodeJS using Express. My problem occurs when I want to use the app (Express instance) in other modules. The following configuration works just fine, but if I replace
var app = module.exports = express();
with
var app = express();
and then use
module.exports = app;
at the bottom of app.js, everything will break down. There will be an error when calling app.get() in the auth module (TypeError: app.get is not a function). Can somebody explain to me why it matters where I export the app object?
app.js
var mongoose = require('mongoose');
var express = require('express');
var bodyParser = require('body-parser');
var debug = require('debug')('app');
var morgan = require('morgan');
var config = require('./config');
var app = module.exports = express();
// --- globals ---
app.set('jwtTokenSecret', config.jwtTokenSecret);
// --- middleware ---
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(morgan('dev'));
// --- routes ---
var courses = require('./routes/courses');
var users = require('./routes/users');
var auth = require('./routes/auth');
app.use('/auth', auth);
app.use('/courses', courses);
app.use('/users', users);
// --- database connection ---
mongoose.set('debug', true);
mongoose.connect(config.database, function(err) {
if (err) {
debug('Could not establish connection to mongodb');
} else {
debug('Successfully connected to mongodb');
}
});
routes/auth.js
var express = require('express');
var router = express.Router();
var moment = require('moment');
var jwt = require('jwt-simple');
var User = require("../models/User");
var debug = require('debug')('app');
var app = require("../app");
// POST /auth
router.post('/', function(req, res, next) {
User.findOne({
'username' : req.body.username
}, function(err, user) {
if (err || !user) {
res.status(401).json({ error: "No user found"});
return;
}
if (user.password != req.body.password) {
res.send(401);
}
debug(app.get('database'));
var expires = moment().add(7, 'days').valueOf();
var token = jwt.encode({
user: user.username,
exp: expires
}, app.get('jwtTokenSecret'));
res.json({
success: true,
token: token
});
});
});
module.exports = router;

It's because you have a circular dependency between app.js and auth.js.
In your app.js file, you are requiring auth.js, and inside auth.js, you are requiring app.js. By moving module.exports = app to the bottom of app.js, it is being called AFTER var auth = require('./routes/auth');. This means that when var app = require("../app"); is called inside auth.js, module.exports will not be yet defined inside app.js, hence leading to the error.

Related

error: "User.findOne is not a function" in MERN

So I am trying to build an authentication system using passport in MERN(MongoDB, Express, React, NodeJS).
I set up everything, I connected react with NodeJS,
The problem is when I am trying to log in or register it shows me,
this error "User.findOne is not a function" in the console and I tried to fix it by looking for any
type mistakes or google it but I didn't find anything online.
Did anyone have a similar mistake and fix it or does anyone know how?
Model Code:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;
const UserSchema = new Schema ({
password: String,
email: String,
}, {
collection: 'information'
})
const User = mongoose.model('information', UserSchema);
module.exports - User;
Passport Code:
const Strategy = require('passport-local').Strategy
const mongoose = require('mongoose')
const User = require('../models/user');
const bcrypt = require('bcryptjs')
const salt = bcrypt.genSaltSync(10);
const SignupStrategy = new Strategy ({ passReqToCallback:true, usernameField: 'email' }, function(req, email, password, done){
User.findOne({email: req.body.email}).lean().exec((err, user) => {
if (err) {
return done(err, null);
}
if (user) {
return done("User already exist", null);
}
const encryptedPassword = bcrypt.hashSync(password, salt);
let newUser = new User({
email,
password: encryptedPassword
})
newUser.save((error, inserted) => {
if (error) {
return done(error, null);
}
delete inserted.password;
return done(null, inserted);
})
})
});
module.exports = SignupStrategy;
Node server:
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const passport = require('./passport/');
const PORT = process.env.PORT || 8080;
const mongoose = require('mongoose');
//I have used password in mongo I just did <password> for security reasons.
const mongoString = mongoose.connect('mongodb+srv://herpryth:<password>#nowyourguest-ga5vy.gcp.mongodb.net/users?retryWrites=true&w=majority', {useNewUrlParser: true})
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', indexRouter);
app.use('/authentication', usersRouter);
app.use(passport.initialize());
app.use(passport.session());
app.listen(process.env.PORT || 8080, process.env.IP || '0.0.0.0');
module.exports = app
Route:
const express = require('express');
const app = express.Router();
const passport = require('../passport')
app.post('/signup', (req, res, next) =>{
passport.authenticate('local-signup', function(error, user, info){
if (error) {
return res.status(500).json({
message: error || 'Something happend',
error : error.message || "Server error"
});
}
return res.json(user);
})(req, res, next);
})
app.post('/signin', function(req, res, next){
passport.authenticate('local-signin', function(error, user, info){
if (error) {
return res.status(500).json({
message: error || 'Something happend',
error : error.message || "Server error"
});
}
return res.json(user);
})(req, res, next);
})
module.exports = app;
React server:
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const passport = require('./passport/');
const PORT = process.env.PORT || 8080;
const mongoose = require('mongoose');
const mongoString = mongoose.connect('mongodb+srv://herpryth:XFXGJakc18wBJLIk#nowyourguest-ga5vy.gcp.mongodb.net/users?retryWrites=true&w=majority', {useNewUrlParser: true})
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', indexRouter);
app.use('/authentication', usersRouter);
app.use(passport.initialize());
app.use(passport.session());
app.listen(process.env.PORT || 8080, process.env.IP || '0.0.0.0');
module.exports = app
Does anyone know how to fix this problem?
There is just a simple mistake in your code
replace with
module.exports = User
to
module.exports - User

receiving 404 not found when calling axios with node and heroku

my react app landing page calls and axios.get on component did mount. I have no issues when running my page locally, however when I deploy with heroku, my axios call returns "404 not found nginx". It feels like a simple fix, although I cant seem to find any threads online that apply to my issue. my server.js is configured as follows
const express = require("express");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const routes = require('./routes');
const dotenv = require("dotenv");
var request = require('request'); // "Request" library
var cors = require('cors');
var querystring = require('querystring');
var passport = require('passport');
var flash = require('connect-flash');
var session = require('express-session');
var morgan = require('morgan');
// var configDB = require('./config/database.js');
require('./config/passport')(passport); // pass passport for configuration
// const fs = require("fs");
var client_id = process.env.DB_SPOTIFY_CLIENT_ID; // Your client id
var client_secret = process.env.DB_SPOTIFY_CLIENT_SECRET; // Your secret
var redirect_uri = process.env.DB_REDIRECT_URI; // Your redirect uri
dotenv.config();
// const port = process.env.PORT || 3030;
const port = 3030
const app = express();
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.set('view engine', 'ejs'); // set up ejs for templating
// required for passport
app.use(session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
// Demo middleware to play with error handling
app.use((req, res, next) => {
const startTime = Date.now();
console.log("Request Time: " + startTime);
console.log(`${req.method} ${req.path}`);
// Request returns 500, default handler returns error
// as html with stack trace in dev, does not terminate server process.
//throw new Error("Bazinga!");
next();
// Request returns 500, default handler returns error as html showing stack trace,
// and terminates server process with error ERR_HTTP_HEADERS_SENT.
//next(new Error("Bazonga!"));
const endTime = Date.now();
console.log(
"Response Time: " + endTime + " Elapsed: " + (endTime - startTime)
);
// Request goes through, error is written to log.
//throw new Error("Bazunga!");
});
// app.use("/node-api/server.js/schedule", (req, res, next) => {
// fs.readFile("data/schedule.json", (err, data) => {
// if (err) {
// // If err, then
// next(err);
// } else {
// res.type("json").send(data);
// }
// });
// });
// routes ======================================================================
require('./routes/LoginRegister.Routes')(app, passport); // load our routes and pass in our app and fully configured passport
app.use("/serverSideStuff/server.js", routes);
app.use((req, res) => {
res.status(404).send("<h2>The path is not valid</h2>");
});
app.listen(port, () => {
console.log(`Magic happens on port ${port}`);
});
you forgot to uncomment this line:
// const port = process.env.PORT || 3030;
and delete this one:
const port = 3030
process.env.PORT will be heroku port :)

Express and Vue. With axios, req.body is not working

Like i said in title. req.body don't work. I saw some examples and that use req.body(body-parser) well. But in my code, req.body is keep undefined. Also i found same problems and they said "app.use(bodyParser.json())" will work. But for me, no. So i ask how can i solve this error. Plz, help me.
This code is simple, Express and Vue login, signin test project. I think problem is in server file.
Server
var express = require("express");
var bodyParser = require("body-parser");
var path = require("path");
const mongoose = require("mongoose");
var index = require("./routes/index.js");
var login = require("./routes/login.js");
var signin = require("./routes/signin.js");
var app = express();
var http = require("http").Server(app);
mongoose.connect("mongodb://localhost:27017/test");
app.use('/', index);
app.use('/api/login', login);
app.use('/api/signin', signin);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set("port", process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'public')));
http.listen(app.get("port"), function() {
console.log("server start in " + app.get("port"));
})
Router
const express = require("express");
const router = express.Router();
const User = require("../models/user.js");
router.post("/", function(req, res, next) {
const id = req.body.id;
const password = req.body.password;
let info = {
error: "false",
words: "",
id: "",
password: ""
}
User.findOne({ id: id }, function(err, user) {
if(err) {
info.error = "true";
info.words = "Unknown Error Come Out.";
return res.send(info);
}
if(!user) {
info.error = "true";
info.words = "Please Check Your ID or Password";
return res.send(info);
}
info.id = id;
info.password = password;
console.log(info);
return res.send(info);
})
});
module.exports = router;
This body can not be resolved because of your middleware declaration order. You can check from the following blog about middleware execution sequence. Basically it equals to middleware declaration order.
https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/
Declare bodyParser middleware before router middleware can solve your problem
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/api/login', login);

Variable added to Node.js express-session is undefined in next request

I am implementing a simple login functionality and storing the data in the express-session but not able to get it back.
In loginDb.js file in login function i am storing the userId in session variable and in getLoginStatus function i am trying to access the userId but it is returing as undefined.
I have gone through many post related to similar issue but nothing helped in my case. Don't know what i am doing wrong here. Below is the code.
server.js
var express = require('express');
var pg = require('pg');
var cookieParser = require('cookie-parser');
var bodyparser = require('body-parser');
var session = require('express-session');
var path = require('path');
const port = 3000;
const loginroute = require('./Routes/login');
var app=express();
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: 'This is a secret',
resave: true,
saveUninitialized:true,
cookie: {
secure: false,
maxAge: 60000
}
}));
//Routes
app.use('/api/loginroute',loginroute);
app.listen(port,function(){
console.log('app listening to port:'+port);
});
login.js
const express = require('express');
const router = express.Router();
const db = require('../DataAccessLayer/loginDb');
router.get('/getLoginStatus', db.getLoginStatus);
router.post('/login', db.login);
module.exports = router;
loginDb.js
var config = require('../Config/config');
var session = require('express-session');
var pg = require('pg');
var pool = new pg.Pool(config.development.db);
function getLoginStatus(req, res, next){
var userId = req.session.userId;
};
function login(req, res, next) {
pool.connect(function(err, client, done) {
if (err) {
console.log("not able to get connection "+ err);
res.status(400).send(err);
}
var q = "select id from nodetest.users where name=$1 and password=$2";
client.query(q, [req.body.username, req.body.password], function(err, result) {
done();
if(err) {
return console.error('error running query', err);
}
if(result.rowCount>0){
req.session.userId = result.rows[0].id;
}
res.send(result.rows);
});
});
};
module.exports = {
login:login,
getLoginStatus:getLoginStatus
};
Set cookieParser secret key similar as that of express-session secret key will fix the issue.
app.use(cookieParser('This is a secret'))
Doc Says
Using cookie-parser may result in issues if the secret is not the same
between this module and cookie-parser.

Node/Express - Route/Function conundrum - circular reference

Smarter programmers, please advise:
two variables coming in from an AJAX post (username, pic)
get them at the route users.js from req.body
have my functions in a file main.Funcs exported to server.js
I can't figure out how to get the variables out of my route and into my server.js, so that I can use them with my functions. Can't figure out how to do it without circular 'require' between routes and mainFuncs.
QUESTIONS:
How do you access variables from routes without (1) making global variables, nor (2) circular require between routes and mainFuncs?
Could set global variables but bad? Some way to call them in a big function that gives access to scope without making global?
server.js
var express = require('express');
var mainFuncs = require('./mainFunctions.js');
mainFuncs.startServer();
mainFuncs.sqlConnectionCheck();
mainFuncs.learnFace(username, picLink);
mainFuncs.js
const client = some api methods, input from route --> api --> json back
var express = require('express');
var users = require('./routes/users');
var bodyParser = require('body-parser');
app.use('/users', users);
var app = express();
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(express.static('public'));
app.use('/', main);
app.use('/users', users);
app.use('/profile', profile);
var mainFuncs = {
startServer: function () {
app.listen(3000, function() {
models.users.sync({ force: true });
models.userPicData.sync({ force: true });
console.log('Listening on port 3000!');
});
},
sqlConnectionCheck: function (){
sequelize
.authenticate()
.then(function(err) {
console.log('Connection to mysql: success.');
})
.catch(function (err) {
console.log('Connection to mysql: failed with these errors: ', err);
});
},
learnFace: function (username, picPath) {
client.faces.detect({ urls: picPath, attributes: 'all' })
.then(function(result){
var newLearn = JSON.parse(result);
var newTid = newLearn.photos[0].tags[0].tid;
var fullNameSpace = username + '#notARealNameSpace';
console.log('You have been registered with the name: ' + username);
client.tags.save(newTid, fullNameSpace, {label: nameString, password: 'optionalPassword'});
client.faces.train(nameString, { namespace: 'urface' });
})
},
};
module.exports = mainFuncs;
routes/users.js
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var app = express();
router.post('/create', function(req,res){
var username = req.body.username;
var picLink = req.body.pic;
});
module.exports = router;
Typically express apps are structured so that the Business Logic, Routes and Express server are in separate locations. The actual logic to your app goes inside a directory /lib. Your routes go inside /routes and your server.js goes into your project root.
/<root>
/lib
/public
/routes
server.js
package.json
Do you mean my mainFuncs should be imported into the router? It just seems like I'm writing most of the program in the routes at that point?
No, your logic goes into separate files inside /lib and your /routes will require it when necessary. This approach is decoupled and allows your logic to live outside of your routes. The logic may be implemented in multiple routes if necessary yet be centralized and easy to maintain. This leaves your routes free to only implement the code needed to determine the response and update session state.
The above code could be structured as so:
server.js
const express = require('express');
const bodyParser = require('body-parser');
const users = require('./routes/users');
// Place DB and any other initialization here in server.js
// so it will be guaranteed to execute prior to the server listening
const app = express();
const port = process.env.PORT || 1337;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static('public'));
app.use('/users', users);
app.listen(port, () => {
console.log(`Listening on ${port}`);
});
module.exports = app;
/lib/learnFace.js
const client = require('<package>'); // Some package etc per your question
function learnFace(username, picPath) {
return client.faces.detect({ urls: picPath, attributes: 'all' })
.then(function(result){
let newLearn = JSON.parse(result);
let newTid = newLearn.photos[0].tags[0].tid;
let fullNameSpace = username + '#notARealNameSpace';
console.log('You have been registered with the name: ' + username);
client.tags.save(newTid, fullNameSpace, {label: nameString, password: 'optionalPassword'});
client.faces.train(nameString, { namespace: 'urface' });
});
}
module.exports = learnFace;
/routes/users.js
const router = require('express').Router();
const learnFace = require('../lib/learnFace');
router.post('/create', (req, res) => {
let username = req.body.username;
let picLink = req.body.pic;
return learnFace(username, picLink)
.then(() => {
return res.sendStatus(201);
})
.catch((err) => {
return res.sendStatus(500);
})
});
module.exports = router;
Also you don't need to require Express in every file like you are no need to, only require the things you need in files that you are using.

Resources