MEAN API , getting undefined is not a function - node.js

I am trying to implement a simple API but get undefined is not a function when I navigate to api/users. Spent hours trying to figure this out, any suggestions would be greatly appreciated.
Stack trace
TypeError: undefined is not a function
at module.exports (//config/routes.js:10:9)
at Layer.handle [as handle_request] (/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/node_modules/express/lib/router/index.js:312:13)
at /U/node_modules/express/lib/router/index.js:280:7
at Function.process_params (//node_modules/express/lib/router/index.js:330:12)
at next (//node_modules/express/lib/router/index.js:271:10)
at logger (//node_modules/morgan/index.js:144:5)
at Layer.handle [as handle_request] (/U/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (//node_modules/express/lib/router/index.js:312:13)
at //node_modules/express/lib/router/index.js:280:7
at Function.process_params (//node_modules/express/lib/router/index.js:330:12)
at next (//node_modules/express/lib/router/index.js:271:10)
at SessionStrategy.strategy.pass (//node_modules/passport/lib/middleware/authenticate.js:318:9)
at SessionStrategy.authenticate (//node_modules/passport/lib/strategies/session.js:67:10)
at attempt (//node_modules/passport/lib/middleware/authenticate.js:341:16)
at authenticate (//node_modules/passport/lib/middleware/authenticate.js:342:7)
I have the following setup.
app.js
'use strict';
var express = require('express');
var env = 'development';
var app = express();
var config = require('./config/config')[env];
require('./config/mongoose')(config);
require('./config/express')(app, config);
require('./config/passport')();
require('./config/routes')(app);
app.listen(config.port, function() {
console.log('Express server listening on port ' + config.port);
console.log('env = ' + app.get('env') +
'\n__dirname = ' + __dirname +
'\nprocess.cwd = ' + process.cwd());
}
express.js
/* jshint -W117 */
var express = require('express'),
logger = require('morgan'),
bodyParser = require('body-parser'),
favicon = require('serve-favicon'),
cookieParser = require('cookie-parser'),
env = 'development',
session = require('express-session'),
passport = require('passport'),
four0four = require('../utils/404')();
module.exports = function(app, config) {
app.use(favicon(config.rootPath + '/favicon.ico'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(session({resave: false, saveUninitialized:false,
secret: 'all is well that ends well'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(logger('dev'));
app.use('/api', require('./routes'));
console.log('About to crank up node');
console.log('PORT=' + config.port);
console.log('NODE_ENV=' + env);
switch (env){
case 'production':
console.log('** BUILD **');
app.use(express.static('./build/'));
// Any invalid calls for templateUrls are under app/* and should return 404
app.use('/app/*', function(req, res, next) {
four0four.send404(req, res);
});
// Any deep link calls should return index.html
app.use('/*', express.static('./build/index.html'));
break;
default:
console.log('** DEV **');
app.use(express.static('./src/client/'));
app.use(express.static('./'));
app.use(express.static('./tmp'));
// Any invalid calls for templateUrls are under app/* and should return 404
app.use('/app/*', function(req, res, next) {
four0four.send404(req, res);
});
// Any deep link calls should return index.html
app.use('/*', express.static('./src/client/index.html'));
break;
}
}
routes.js
var four0four = require('../utils/404')(),
auth = require('../config/auth'),
users = require('../controllers/users'),
mongoose = require('mongoose'),
User = mongoose.model('User');
module.exports = function(app) {
app.get('/users', auth.requiresRole('admin'), users.getUsers);
app.post('/users', users.createUser);
app.put('/users', users.updateUser);
app.post('/login', auth.authenticate);
app.post('/logout', function(req, res) {
req.logout();
res.end();
});
app.all('/*', four0four.notFoundMiddleware);
}
auth.js
var passport = require('passport');
exports.authenticate = function(req, res, next) {
req.body.username = req.body.username.toLowerCase();
var auth = passport.authenticate('local', function(err, user) {
if (err) {return next(err);}
if (!user) {res.send({success:false});}
req.login(user, function(err) {
if (err) {return next(err);}
res.send({success:true, user:user});
});
});
auth(req, res, next);
};
exports.requiresApiLogin = function(req, res, next) {
if (!req.isAuthenticated()) {
res.status(403);
} else {
next();
}
};
exports.requiresRole = function(role) {
return function(req, res, next) {
if (!req.isAuthenticated() || req.user.roles.indexOf(role) === -1) {
res.status(403);
res.end();
} else {
next();
}
};
}

I solution to this problem was a complete refactor of my routes.js file. I also removed this line from the app.js
require('./config/routes')(app);
Here is how the routes.js file looks after the refactor.
var four0four = require('../utils/404')(),
auth = require('../config/auth'),
users = require('../controllers/users'),
mongoose = require('mongoose'),
User = mongoose.model('User'),
router = require('express').Router();
router.get('/users', auth.requiresRole('admin'), users.getUsers);
router.post('/users', users.createUser);
router.put('/users', users.updateUser);
router.post('/login', auth.authenticate);
router.post('/logout', logoutUser);
router.all('/*', four0four.notFoundMiddleware);
module.exports = router;
//////////////
function logoutUser (req, res){
req.logout();
res.end();
}

Related

Can't use passport.authenticate('local')

I posted question here cuz I my passport.authenticate('local') shows nothing, so I cannot use login function. I can activate singup api that I created, but somehow I cannot use my login api that I created as well.
Here is my code below.
var createError = require('http-errors');
var express = require('express');
var ejsMate = require('ejs-mate');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var config = require('./config')
var passport = require('passport')
// var session = require('express-session')
var homeRouter = require('./routes/home');
var usersRouter = require('./routes/users');
const mongoose = require('mongoose')
const url = config.mongoUrl
const connect = mongoose.connect(url)
connect.then((db) => {
console.log('Connected correctly to server')
}, (err) => {console.log(err)})
var app = express();
// view engine setup
//GET, POST, DELETE, PUT
app.engine('ejs', ejsMate)
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(passport.initialize())
//localhost:3000/
app.use('/', homeRouter);
//localhost:3000/users
app.use('/users', usersRouter);
app.use(express.static(path.join(__dirname, 'public')))
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
var express = require('express');
const bodyParser = require('body-parser')
var User = require('../models/users')
var passport = require('passport')
var authenticate = require('../authenticate')
var router = express.Router();
router.use(bodyParser.json())
/* GET users listing. */
router.get('/', (req, res, next) => {
console.log("HAHA")
User.find({})
.then((Users) => {
res.statusCode = 200
res.setHeader('Content-Type', 'application/json')
res.json(Users)
}, (err) => next(err))
.catch((err) => next(err))
});
router.post('/signup', (req, res, next) => {
User.register(new User({username: req.body.username}),
req.body.password, (err, user) => {
if(err) {
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.json({err: err});
}
else {
if(req.body.firstname)
user.firstname = req.body.firstname
if(req.body.lastname)
user.lastname = req.body.lastname
user.save((err, user) => {
if(err) {
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.json({err: err});
return;
}
passport.authenticate('local')(req, res, () => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json({success: true, status: 'Registration Successful!'});
})
})
}
})
});
router.post('/login', passport.authenticate('local'), (req, res) => {
var token = authenticate.getToken({_id: req.user._id});
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json({success: true, token: token, status: 'You are successfully logged in!'});
})
router.get('/logout', (req, res, next) => {
console.log(req.session)
if (req.session) {
req.session.destroy();
res.clearCookie('session-id');
res.redirect('/');
}
else {
var err = new Error('You are not logged in!');
err.status = 403;
next(err);
}
});
module.exports = router;
router.post('/login', passport.authenticate('local') ---> show nothing it keep showing me an error
I need some advice and help.

error 404 while authenticating with passport js local

Really stuck on the same issue for much time. Tried many things but all to no use. Please help.
The register module works fine but the login doesn't. It returns 404 error upon hitting submit button. Attached are the appropriate code documents.
The login module is supposed to redirect to contactlist upon successful authentication.
Thank you very much!.
app.js
let createError = require('http-errors');
let express = require('express');
let path = require('path');
let cookieParser = require('cookie-parser');
let logger = require('morgan');
var bodyParser = require('body-parser');
let Login = require('../models/login')
let passport = require('passport');
let LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
//database setup
let mongoose = require('mongoose');
let DB = require('./db');
//point mongoose to the db URI
mongoose.connect(DB.URI);
let mongoDB = mongoose.connection;
mongoDB.on('error',console.error.bind(console,'Connection Error in Mongo'));
mongoDB.once('open',()=>{
console.log("Connected to MongoDB");
})
let indexRouter = require('../routes/index');
let usersRouter = require('../routes/users');
let loginRouter = require('../routes/login');
let authRouter = require('../routes/auth');
const exp = require('constants');
let app = express();
// view engine setup
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('express-session')({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(express.static(path.join(__dirname, '../../public')));
app.use(express.static(path.join(__dirname,'../../node_modules')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/login', loginRouter);
app.use('/', authRouter);
// passport config
passport.serializeUser(Login.serializeUser());
passport.deserializeUser(Login.deserializeUser());
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error',{ title: 'error' });
});
module.exports = app;
auth.js
let express = require('express');
let router = express.Router();
let passport = require('passport');
let user = require('../models/user');
router.post('/register',(req,res,next)=>{
user.register(new user({
username:req.body.username,
}),
req.body.password,(err, newUser) =>{
if(err){
return res.redirect('/login/register')
}
else{
req.login(newUser,(err) => {
res.redirect('/login/contactlist')
})
}
}
)
});
router.post('/', passport.authenticate('local', { failureRedirect: '/login/contactlist' }),
function(req, res) {
res.redirect('/login/contactlist');
});
module.exports = router;
login.js
let express = require('express');
let router = express.Router();
let passport = require('passport');
/* GET index page. */
let Login = require('../models/login')
let Contact = require('../models/contact')
router.get('/', function(req, res, next) {
Login.find((err,loginList)=>{
if(err){
return console.error(err);
}
else {
//console.log(loginList);
res.render('login/login', { title: 'Login',loginList: loginList,user: req.user });
}
});
});
router.get('/register', function(req, res, next) {
res.render('login/register')
});
/* GET contactlist page. */
router.get('/contactlist', function(req, res, next) {
Contact.find((err,contactList)=>{
if(err){
return console.error(err);
}
else {
res.render('login/contactlist', { title: 'contactlist',contactList: contactList });
}
});
});
/* GET update page. */
router.get('/update/:id', function(req, res, next) {
let id = req.params.id;
Contact.findById(id, (err, contactToEdit) => {
if(err)
{
console.log(err);
res.end(err);
}
else
{
//show the edit view
res.render('login/update', {title: 'Update', contact:contactToEdit })
}
});
});
router.get('/delete/:id', function(req, res, next) {
let id = req.params.id;
Contact.remove({_id: id}, (err) => {
if(err)
{
console.log(err);
res.end(err);
}
else
{
// refresh the contacts list
res.redirect('/login/contactlist');
}
});
});
/* POST update page. */
router.post('/update/:id', function(req, res, next) {
let id = req.params.id
let newContact = Contact({
"_id":id,
"email":req.body.email,
"number": req.body.number,
"name":req.body.name
});
Contact.updateOne({_id: id},newContact,(err)=>{
console.log(newContact);
if(err){
console.log(err);
res.end(err);
}
else{
console.log(id)
console.log("POST update");
res.redirect('/login');
}
});
});
/* POST contactlist page. */
router.post('/contactlist', function(req, res, next) {
res.render('login/contactlist', { title: 'contactlist' });
});
module.exports = router;

Problem In running code for Token-based authentication-passport using NodeJS & ExpressJS

app.js
const express = require('express');
const path = require('path');
const logger = require('morgan');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/dishes', dishRouter);
app.use('/dishes/:dishId', dishRouter);
module.exports = app;
authenticate.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const jwt= require('jsonwebtoken');
const config = require('./config.js');
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
exports.local = passport.use(new LocalStrategy(User.authenticate()));
exports.getToken=function(user){
return jwt.sign(user, config.secretKey,
{expiresIn: 3600});
};
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: config.secretKey
};
exports.jwtPassport = passport.use(new JwtStrategy(opts,
(jwt_payload, done)=>{
User.findOne({_id:jwt_payload._id}, (err, user)=>{
if(err){
return done(err, false);//(optional params)callback that passport will pass your startegy here
}
else if(user) {
return done(null, user);
}
else{
return done(null, false);//if we want we can create a new user
}
});
}));
exports.verifyUser = passport.authenticate('jwt', { session: false });
config.js
module.exports={
'secretKey':'12345-67890-09876-54321',
'mongoUrl':'mongodb://localhost:27017/conFusion'
}
dishRouter.js
const express = require('express');
const bodyParser = require('body-parser');
const authenticate = ('../authenticate');//higher level folder
const Dishes = require('../models/dishes');
const dishRouter = express.Router();
dishRouter.use(bodyParser.json());
dishRouter.route('/')
.get((req,res,next) => {
//performing find operation
Dishes.find({}).then((dishes)=>{
res.statusCode = 200;
res.setHeader('Content-Type','application/json');
//take a input as a json string & send it back to the client(json response)
res.json(dishes);
},(err)=>next(err)).catch((err)=>next(err));
})
.post(authenticate.verifyUser, (req, res, next) => {
Dishes.create(req.body).then((dishes)=>{
console.log('dish created...',dishes);
res.setHeader('Content-Type','application/json');
res.json(dishes);
},(err)=>next(err)).catch((err)=>next(err));
})
.put(authenticate.verifyUser,(req, res, next) => {
res.statusCode = 403;
res.end('PUT operation not supported on /dishes');
})
.delete(authenticate.verifyUser,(req, res, next) => {
Dishes.remove({}).then((resp)=>{
res.statusCode = 200;
res.setHeader('Content-Type','application/json');
//take a input as a json string & send it back to the client(json response)
res.json(resp);
},(err)=>next(err)).catch((err)=>next(err));
});
// Other routes
module.exports = dishRouter;
While Running the code I got the following Error
While running this code I got Error: Route.post() requires a callback function but got a [object Undefined]
at Route. [as post] (D:\EDUCATION\nodejs\node-express generator\conFusionServer\node_modules[4mexpress[24m\lib\router\route.js:202:15)
at Object. (D:\EDUCATION\nodejs\node-express generator\conFusionServer\routes\dishRouter.js:21:4) and Error app.js:28 th line I am unable fix this error anyone can help me to fix this error
There's a missing require in dishRouter.js; line 4.
Fix:
const authenticate = require('../authenticate');

Express handling URIError: Failed to decode param

var express = require('express');
var app = express();
app.get('*', function (req, res) {
var host = req.get('Host');
return res.redirect(['https://', host, req.url].join(''));
});
var server = app.listen(8080, function () {
console.log('starting');
});
I have a simple script that redirects http to https. This is working fine except when there is a malformed url for example: website.com/%c0%ae%c0%ae. It displays something like:
URIError: Failed to decode param '/%c0%ae%c0%ae'
at decodeURIComponent (native)
at decode_param (/...<PROJECT DIRECTORY>.../node_modules/express/lib/router/layer.js:167:12)
at Layer.match (/.../node_modules/express/lib/router/layer.js:143:15)
at matchLayer (/.../node_modules/express/lib/router/index.js:557:18)
at next (/.../node_modules/express/lib/router/index.js:216:15)
at expressInit (/.../node_modules/express/lib/middleware/init.js:33:5)
at Layer.handle [as handle_request] (/.../node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/.../node_modules/express/lib/router/index.js:312:13)
at /.../node_modules/express/lib/router/index.js:280:7
at Function.process_params (/.../node_modules/express/lib/router/index.js:330:12)
It's not nice when a user can randomly see where my project files are in the server. Any way to handle this error?
Thanks #Oleg for the tip. But somehow your solution wasn't logging error for me. Here's what I have come up with:
var express = require('express');
var app = express();
app.use(function(req, res, next) {
var err = null;
try {
decodeURIComponent(req.path)
}
catch(e) {
err = e;
}
if (err){
console.log(err, req.url);
return res.redirect(['https://', req.get('Host'), '/404'].join(''));
}
next();
});
app.get('*', function (req, res) {
return res.redirect(['https://', req.get('Host'), req.url].join(''));
});
var server = app.listen(8080, function () {
console.log('Starting');
});
Possible workaround:
var express = require('express');
var app = express();
app.get('*', function (req, res) {
// redirect regular paths
var host = req.get('Host');
return res.redirect(['https://', host, req.url].join(''));
});
// your express error handler
app.use(function(err, req, res, next) {
// in case of specific URIError
if (err instanceof URIError) {
err.message = 'Failed to decode param: ' + req.url;
err.status = err.statusCode = 400;
// .. your redirect here if still needed
return res.redirect(['https://', req.get('Host'), req.url].join(''));
} else {
// ..
}
// ..
});
var server = app.listen(8080, function () {
console.log('starting');
});
var express = require('express');
var app = express();
// handles 400 error
app.use((err, req, res, next) => {
if (!err) return next();
return res.status(400).json({
status: 400,
error: 'OOps! Bad request',
});
});
Edited:
The code snippet should be placed as the last route, it checks if there is an error that was skipped by other routes, which obviously there is, and sends a default response. This error happens when you add % as last character of an API endpoint..

404 when attempting rooting with param on Express

i get 404 error when rooting with param , whereas all other rootings defined on my rootes/users.js file work perfectly , for example i get the desire result when i call :
localhost:3000/users/users .
but get 404 when i call localhost:3000/users/users/12315454 which should correspond to the rooter /users:user_id in my users.js (you can find it below)
var express = require('express');
var router = express.Router();
var User = require('../models/user');
router.route('/users:user_id')
.get(function(req, res) {
console.log("attempting user");
User.findById(req.params.user_id, function(err, place) {
if (err)
res.send(err);
res.json(place);
});
})
.put(function(req, res) {
console.log("attempting to update user");
User.findById(req.params.user_id, function(err, place) {
if (err)
res.send(err);
user.username = req.body.name;
user.visitedPlaces = req.body.visitedPlaces;
user.likedItems = req.body.likedItems;
//user.local.email= req.body.email;
user.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'user updated!' });
});
});
})
.delete(function(req, res) {
User.remove({
_id: req.params.user_id
}, function(err, bear) {
if (err)
res.send(err);
res.json({ message: 'Successfully deleted' });
});
});
router.route('/users')
// get all the users (accessed at GET http://localhost:8080/api/users)
.get(function(req, res) {
User.find(function(err, places) {
if (err)
res.send(err);
res.json(places);
});
});
router.route('/adduser')
.post(function(req, res) {
var user = new User();
user.password = user.generateHash (req.body.password); // set the users name (comes from the request)
user.username = req.body.username;
console.log(req.body)
console.log("user name :"+req.body.username);
user.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'user created!' });
});
});
module.exports = router;
my app.js config
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;
var mongo = require('mongoskin');
var mongoose = require('mongoose');
var configDB = require('./config/database.js');
var port = process.env.PORT || 3030;
var router = express.Router();
// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database
//Facebook app credentials
var FACEBOOK_APP_ID = '******09';
var FACEBOOK_APP_SECRET = '9a*******3';
//app secret for dev = 9adfcaa6d7989d8adc12852badcf69f3
// app ifd for dev = 492502667544609
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'app')));
//var routes = require('./routes/index');
require('./config/passport')(passport); // pass passport for configuration
var users = require('./routes/users');
var places = require('./routes/places');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// set up our express application
app.use(logger('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms
// required for passport
app.use(session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session());
app.use(favicon());
//app.use(flash()); // use connect-flash for flash messages stored in session
// Make our db accessible to our router WARNING THIS MUST BE PUT before the rooting stuff above
app.use('/api', router);
app.use('/places', places);
app.use('/users', users);
// routes ======================================================================
require('./routes/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
app.get('/', function(req, res, next) {
res.sendfile('./app/index.html');
});
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
// test authentication
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { console.log("is authenticated");
return next(); }
console.log("not authenticated");
res.redirect('/')
}
// launch ======================================================================
console.log('The magic happens on port ' + port)
module.exports = app;
Add a slash in your route, between the users and :user_id:
router.route('/users/:user_id')
^---------here

Resources