How to pass a parameter to middleware function in Express JS? - javascript

// state edit route
app.get("/map/:symbol/edit", isLoggedIn, function(req, res){
State.findOne({symbol: req.params.symbol}, function(err, state){
if(err){
console.log(err);
} else
{
res.render("edit", {state: state});
}
});
});
In the above code snippet, isLoggedIn is the middleware function to check for authentication. Its definition is given below:
// middleware function
function isLoggedIn(req, res, next){
if(req.isAuthenticated()){
return next();
}
res.redirect("/admin");
}
So, the question is, how to pass a parameter like a string, an integer or a path variable to the middleware function so that it can be used in the routing url ?

I had the same requirement and this approach works for me.
Middleware file validate.js
exports.grantAccess = function(action, resource){
return async (req, res, next) => {
try {
const permission = roles.can(req.user.role)[action](resource);
// Do something
next();
}
catch (error) {
next(error)
}
}
}
Use of middleware in route file. grantAccess('readAny', 'user')
router.get("/",grantAccess('readAny', 'user'), async (req,res)=>{
// Do something
});

Follow this approach, it might do the job for you
app.use(function(req, res, next){
console.log(req);
this.req = req;
// assign value like this
this.req.body.custom_data = ['zz', 'aaa', ....];
next();
});
app.get("/map/:symbol/edit", isLoggedIn, function(req, res){
State.findOne({symbol: req.params.symbol}, function(err, state){
if(err){
console.log(err);
} else {
res.render("edit", {state: state});
}
});
});
function isLoggedIn(req, res, next){
console.log(req.body);
if(req.isAuthenticated()){
return next();
}
res.redirect("/admin");
}

This is the way I'm using it, I take a little bit of Hardik Raval answer.
helpers.validateRole = (roles) => {
return async (req, res, next) => {
try {
const authHeader = req.headers['authorization']
const token = authHeader && authHeader.split(' ')[0]
if (token == null) return res.json({error:true, msg: "Unauthorized"})
const user = jwt.decode(token)
let isValid = false
roles.map((r,i)=>{
if (r === user.role){
isValid = true
}
})
if (isValid){
// User role is valid
next();
}else{
// User role is not valid
util.returnError("Unauthorized", res);
}
}
catch (error) {
next(error)
}
}
}
And I called like this.
router.get( "/requirements/list_of_requirements/:page/:rows", isAuthenticated, validateRole([6]), async (req, res) => {
//* All the logic
})

Related

How to use req and res inside socket express.js

How to use req and res inside socket express.js (Node)
module.exports = function (io) {
io.use(function(socket, next){
if (socket.handshake.query && socket.handshake.query.token){
jwt.verify(socket.handshake.query.token, 'SECRET_KEY', function(err, decoded) {
if (err) return next(new Error('Authentication error'));
socket.decoded = decoded;
/*
Can i use here req and res here ?
i.e req.constant
req.constant is my middleware that
*/
next();
});
}
else {
next(new Error('Authentication error'));
}
})
.on('connection', function(socket) {
// Connection now authenticated to receive further events
socket.on('message', function(message) {
io.emit('message', message);
});
}
This is another file where I put these values
let connection = async(req, res, next) =>{
req.constants = require('../constants');
next();
}
If i do write io.use(function(req, res, socket, next){ }
that does not work if i access it directly it does not work how can i use it ? Please guide on this req.constant should get called
Thanks

Express.js - Middleware - not executing next()

I'm trying to execute a post function that has a next(); in the middle of the code, so i'm exporting the definition of the function from another file and trying to call it from express router. But it doesn't execute.
--EDIT
I've tried the regular definition as suggested above, but it stops when "next();" is called and returns
Cannot POST /registerUser
index.js
[...]
//Definição e Chamada de Componentes
const userLogin = require('./userControl/accessControl');
const userRegister = require('./userControl/registerControl');
[...]
var router = express.Router(); // get an instance of the express Router
//Definição das Rotas
//==============================================================================
router.post('/login', userLogin.login);
router.post('/forgotPassword', userLogin.forgotPassword);
router.post('/registerUser', function(req, res, next) {userRegister.registerUser});
app.use('/', router);
// START THE SERVER
// =============================================================================
app.set('env', 'production');
app.listen(port);
console.log('API Listening on Port ' +port+'');
registerControl.js
exports.registerUser = function(req, res, next) {
var query = "INSERT INTO [user] (name, email, phone, login, password, enabled, profile) VALUES ('example', 'example#abc.si', 'XXXXXXXXXXXX', 'ADMIN', '12345', 1, 'TEST')
global.conn.request()
.query(query)
.then(result => {
var userId = result.recordset[0].id;
console.log(userId);
if (result.rowsAffected[0] == 0) {
res.sendStatus(500);
}
else {
req.body.userId = userId;
next();
}
})
.catch(err => res.json(err));
}, function(req, res) {
var query = "INSERT INTO [user_company] (company_id, user_id) VALUES ("+req.body.companyId+", "+req.body.userId+");"
global.conn.request()
.query(query)
.then(result => {
if (result.rowsAffected[0] == 0) {
res.sendStatus(500);
}
else {
res.sendStatus(200);
}
})
.catch(err => res.json(err));
};
Thanks!
Instead of
router.post('/registerUser', function(req, res, next)
{userRegister.registerUser});
maybe try
router.post('/registerUser', userRegister.registerUser);
Just like you did in the above forgotPassword route.

Req.isAuthenticated turns to false

When I log in I'm authenticated but when I switch to another page req.isAuthenticated returns false and I'm on login panel. The second thing is when I log in I keep getting an error "can't set headers after they are sent". Here is my code:
const isLoggedIn = (req, res, next) => {
if (req.isAuthenticated()) {
return res.end();
} else {
return res.redirect("/login");
}
}
module.exports = (app, passport) => {
app.post("/login", (req, res, next) => {
passport.authenticate("local-login",
(err, user, info) => {
if(!user) {
res.render("index", { message: "Wrong password or login!" })
} else {
req.login(user, (error) => {
if (error) return next(error);
console.log("AUTH: ", req.isAuthenticated()) <--- RETURNS TRUE
return res.render("map", { name: user.name });
});
}
})(req, res, next);
});
app.get("/", (req, res) => {
return res.render("index"); // load the index file
})
app.get("/login", (req, res) => {
return res.render("index"); // load the index file
})
app.get("/map", isLoggedIn, (req, res) => {
return res.render("map");
});
app.get("/vehicles", isLoggedIn, (req, res) => {
return
});
app.get("/settings", isLoggedIn, (req, res) => {
res.render("settings");
});
app.get("/logout", (req, res) => {
req.logout();
res.redirect("/");
});
};
Login page will of course give you req.isAuthenticated true because you are just authenticated by passport middleware.
Passport will return req.isAuthenticated true until you are not getting logged out and it will set req.isAuthenticated false when you hit /logout route
So maintaining the state of user you have to use sessions for storing state of
application.
find below link : https://www.npmjs.com/package/express-session
you are getting "can't set headers after they are sent". because you are returning response twice. one that is after req.isAuthenticated() getting turn true and second is like you are again rendering a map page.
so instead of return res.end() you should have to use next()
const isLoggedIn = (req, res, next) => {
if (req.isAuthenticated()) {
req.session.isAuthenticated = true;
res.locals.isAuthenticated = true;
res.locals.user =req.user;
next(); //If you are authenticated, run the next
} else {
return res.redirect("/login");
}
}

How to show logged on username in NodeJS/ExpressJS/Passport?

I want to display the username in case the user is logged in (function 3). Initially, I only had function 1. I've changed function 1 into function 2 in order to display the username of the logged in user. I am not sure if this is the right way to do this, because I don't know if I need parameters res and next, and function next(). Any idea?
I am using NodeJS, ExpressJS and Passport
1.
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next()
} else {
res.redirect('/login')
}
}
2.
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return true
}
return false
}
3.
router.get('/', function(req, res) {
if (isLoggedIn) {
res.render('index', {
username: req.user.username
})
} else {
res.render('index')
}
})
You are pretty much doing the right but calling the method isLoggedIn like a variable. I have corrected the same below.
2.
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return true;
}
return false;
}
3.
router.get('/', function(req, res, next) {
if (isLoggedIn(req, res, next)) {
res.render('index', {
username: req.user.username
});
} else {
res.render('index');
}
});
Also, you can refactor the isLoggedIn method as below.
function isLoggedIn(req, res, next) {
return req.isAuthenticated();
}

Providing Custom Params In Express Middleware

I am having a problem with my Node.js app. In short I want to pass custom parameters into my middleware function other than just req, res, and next.
Middleware file:
var DB = require('./DB.js');
function requirePermissions(e) {
console.log('nope')
}
module.exports = requirePermissions;
Route:
router.post('/posts', requirePermissions('post_creation'), function(req, res) {
var o = req.body,
title = o.post.title,
content = o.post.content;
res.send('made it');
});
I have confirmed that using function requirePermissions(req, res, next) {} will work, but I do not understand how to include my own parameters.
Your function requirePermissions should return another function which will be the actual middleware:
function requirePermissions(e) {
if (e === 'post_creation') {
return function(req, res, next) {
// the actual middleware
}
} else if (e === 'something_else') {
return function(req, res, next) {
// do something else
}
}
}
You can also do it like that:
function requirePermissions(e) {
return function(req, res, next) {
if ('session' in req) {
if (e === 'post_creation') {
// do something
} else if (e === 'something_else') {
// do something else
}
}
}
}
You can just create an anonymous function for your middleware that lets you call your actual function with some additional arguments:
router.post('/posts', function(req, res, next) {
requirePermissions('post_creation', req, res, next);
}, function(req, res) {
var o = req.body,
title = o.post.title,
content = o.post.content;
res.send('made it');
});
Or, you can use .bind() to preprend arguments:
router.post('/posts', requirePermissions.bind('post_creation'), function(req, res) {
var o = req.body,
title = o.post.title,
content = o.post.content;
res.send('made it');
});
This will call your requirePermissions() functions with four arguments like this:
requirePermissions('post_creation', req, res, next)

Categories

Resources