storing express "res" variable and using it later? - javascript

I have a simple nodeJs server with express and I have an external module that handles sending the response to the requests. In order for this file to work, it needs to access express res variable. Before, I used to send this variable to the module functions to use it, but then I tried to use a middleware to store this variable in the module and not send it every time I'm calling a function, and it worked!
This is the code:
// app.js
var http = require('http');
var express = require('express');
var app = express();
var response = require('./response.js');
// store the value of 'res' in the response module
app.use(function(req, res, next) {
response.setRes(res);
next();
});
app.get("/", function(req, res){
response.success("Welcome"); // works fine
});
app.get("/images", function(req, res){
response.forbidded("Forbidded"); // works fine
});
var server = http.createServer(app);
server.listen(3000, function(){
console.log("listening... ");
});
and this is the other module
// response.js
exports.setRes = function(_res){
res = _res;
};
exports.success = function(msg){
res.status(200).send(msg);
};
exports.forbidded = function(msg){
res.status(403).send(msg);
};
My question is: Is this a good approach? and will this affect my application if the number of users increases (I'm worried that one user might get the res of another user)

Related

Cannot GET / while using a grammar Api

I am trying to use API to check the grammar of the sentence. but when I don't know it is giving me the error Cannot GET / please tell me where I am wrong.
const express = require('express');
const https = require('https');
const app = express();
app.get('/', function(req, res){
res.sendFile(__dirname + "/index.html");
});
app.post("/", function(req, res){
const text = req.body.cityName;
const url = "https://www.stands4.com/services/v2/grammar.php?uid=8816&tokenid=u9K3iEcIcjmS84B6&text=" + text + "&format=json";
https.get(url,function(response){
response.on("data", function(data){
const grammar = JSON.parse(data);
const fault = grammar.matches.message;
console.log(fault);
res.write("<p>The problem in text :" + fault + "</p>");
res.send();
});
});
});
app.listen(port = 3000, function(){
console.log("Server is running on port 3000 ");
})
Are you trying to access localhost:3000 via the browser? if so you're using app.post change it to app.get
This error usually occurs when target an invalid endpoint, make sure that you use correct url and correct method
Your controller is a POST controller thus the error. You either do a post call or you change to the controller to GET.
app.get("/", function(req, res) ...
If you are trying to hit your own API, then the problem is that your controller is being a POST controller. That is why it throws you Cannot GET.
You can change app.post to app.get or, you can try calling POST method instead of GET.

How to implement login system in node.js and expressJs [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am developing an app in node.js and using expressJs, but I am a PHP developer, I know that in PHP we can use session to implement login and I thought in node.js case is the same, so as I searched I found the express-session module, and I tried to implement this way.
This app.js file
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
app.set('port', process.env.PORT || 3000);
app.set('view engine', 'ejs');
app.set('views', 'app/views');
app.use(require('./routes/login_api'));
app.use(require('./routes/login'));
app.use(require('./routes/Index_api'));
app.use(require('./routes/index'));
var server = app.listen(app.get('port'), () => {
console.log('Server is listening on ' + app.get('port'));
});
So as you can see I have four different routes, /routes/login renders the login.ejs template, /routes/login_api handles the requests and response of the login page,
/routes/Index_api, /routes/Index_api (which is my dashboard), is the same way. This is `login_api
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var session = require('express-session');
var mysql = require('mysql');
var conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'fmis'
});
conn.connect();
router.use(bodyParser.urlencoded({
extended: false
}));
router.use(bodyParser.json());
router.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
router.post('/login_api', function(req, res) {
var Username = req.body.Username;
var Password = req.body.Password;
var query = "SELECT `User_Id`, `User_Username`, `User_Password`, `User_Name`, `User_Last_Name`, `User_Type`, `User_Photo` FROM `users` WHERE `User_Deleted` = 0 AND `User_Username`='" + Username + "' AND `User_Password` = '" + Password + "'";
conn.query(query, function(err, result) {
if (err) {
console.error(err);
res.end();
} else {
if (result.length == 1) {
req.session.Username = result[0].User_Username;
req.session.Password = result[0].User_Password;
req.session.UserType = result[0].User_Type;
}
}
console.log(req.session.Username); // gives the right result
});
console.log(req.session.Username); // gives the undefined
});
As far as I know the session.Username is a global variable (as it is in PHP)
so it should be accessible in everywhere but when I access it in routes/index route it gives the undefined result, not even that if write the console.log(req.session.Username); inside query callback function it gives the right result which is returned from the database but when I place it out side query callback function it gives undefined result.
So any suggesstion please help me
You need to understand the async and non-blocking nature of Node.js. When you call conn.query the process does not block and moves on to the next statement which is console.log (outside the callback). Most probably the callback hasn't been called yet. Callback will be called at an arbitrary time when either the result or error is available. That's why you see that "weird" behaviour. The order of execution is not necessarily the order of statements.
A Quick Solution:
I recommend Passport. It is popular and easy to use for handling authentication.
You can use it as a middleware which is cleaner and get access to the current user simply by req.user which is available in the request context. It has different authentication strategies, including OAuth, and easy to work with.
NOTE: It requires the session and cookie-parser.
In your particular application see:
LocalStrategy to load user details from database;
de/serializeUser for reading and writing user data from session;
Also you need to use passport.initialize() and passport.session() middlewares. See the project's page for details on how to use it.

PassportJS - Getting payload data before it is passed to passport.authenticate as request parameter

There is a passport.js implementation which is being used for LDAP-auth which works. Now the next step is to encrypt the password on the client-side using Crypto-js as follows:
Client-side angular-js controller
$scope.authenticate = function () {
var auth = new login();
auth.username = $scope.username;
auth.password = CryptoJS.AES.encrypt($scope.password); //// HERE
auth.$save(function (response){
console.log(response);
},function(err){
console.log(err);
});
}
Server-side service
.....
.....
app.post('/login', passport.authenticate('ldapauth'), (req, res) => {
console.log("req.user: ",req.user);
req.session.username = req.user[ldap.username];
req.session.userModel = req.user;
res.status(200).send({"success": 'success'});
});
.....
On the server-side service before calling passport.authenticate with the request 'req' the aes encrypted password needs to be decrypted. How can that be implemented here? (The question is not about encryption but how to get data before it gets passed to passport.authenticate as request)
#Abhijay Ghildyal I don't think they understood your question. It is indeed possible to intercept the request before it gets passed to passport.authenticate(). What you'd want to do is to add this passage of code to your express.js or whichever file you did your express server implementation in. Also I am decrypting the request.body here instead of req.user since at that point of time the user is not yet logged in, however if it's different in your case then that's fine you can decrypt req.user the same way. (The variable app here is the name of your server i.e var app = express();)
app.use(function(req, res, next) {
if(req.url === '/login'){
//CryptoJS.AES.decrypt() is Assumed to be the decrypter function here.
req.body = CryptoJS.AES.decrypt(req.body);
console.log(req.body); //To view decrypted body
}
next();
});
That is it. This middleware function will be reached first before the passport.authenticate() function. Just make sure if you're applying this to req.body you add these lines of codes first, after importing the bodyParser (bodyParser = require('body-parser');) before the passage above.
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());

retain query string after Stormpath authentication and authorization in node express site

I have a node express app , using express-stormpath for authentication/authorization
I have a GET route which is called with certain jquery parameters.
If the user is logged in everything is working as expected.
If not the user login screen is shown.
After stormpath authentication and authorization is done my query params are lost.
Is there any way to retain those?
app.get('/myRoute', stormpath.groupsRequired(['admin']), function(req, res){
console.log('req.query ',req.query);
//do somehting with the query data
res.sendStatus(200);
});
after authentication req.query is {}.
Any ideas?
Thank you for the question, I work at Stormpath and I'm more than happy to help. Our express-stormpath library is open source, and we're always happy to fix bugs and review pull requests.
Can you tell me which version of our library you are using? At the moment I'm not able to reproduce the problem you are seeing. Here is a quick example that I put together with the latest version, 3.0.1:
'use strict';
var express = require('express');
var stormpath = require('express-stormpath');
var app = express();
var port = process.env.PORT || 3000;
app.use(stormpath.init(app));
app.get('/admins', stormpath.groupsRequired(['admins']), function(req, res){
res.json(req.query);
});
app.on('stormpath.ready',function () {
console.log('Stormpath Ready');
});
app.listen(port, function () {
console.log('Server listening on http://localhost:' + port);
});
With this example, I do the following:
1.) Assert that I'm not logged in, by deleting all my cookies for localhost.
2.) Type /admin?foo=bar into the URL bar.
3.) I am redirected to the login page.
4.) I login with valid credentials.
5.) I am redirected to /admins?foo=bar, as expected, and I see the req.query object in the body of the page that is rendered. This is only true if the user is in the admins group, if they are not I will see the "Unauthorized" error message page.
Can you compare my steps and my example to your application, and let us know if there are any differences? Thanks!
I don't think that stormpath is removing query from request.
But we can check it by adding middlewhare before stormpath initialization:
var express = require('express');
var stormpath = require('express-stormpath');
var app = express();
// binding middleware to assign req.query to req.q param
app.use(function(req, res, next) {
req.QUERY = req.query;
next();
});
function restoreQuery(req, res, next) {
req.query = req.QUERY;
next();
}
app.use(stormpath.init(app, {
// Optional configuration options.
}));
app.get('/myRoute',
stormpath.groupsRequired(['admin']),
restoreQuery,
function(req, res){
console.log('req.query ',req.query);
//do somehting with the query data
res.sendStatus(200);
});

NodeJS fill "req" from other function

I've got a NodeJS + Express Server setup with a router that looks like this:
app.route('/clients/:clientId)
.get(users.ensureAuthenticated, clients.read)
.put(users.ensureAuthenticated, clients.hasAuthorization, clients.update)
.delete(users.ensureAuthenticated, clients.hasAuthorization, clients.delete);
app.param('clientId', clients.clientByID);
My Problem is that users.ensureAuthenticated fills the req parameter with the current user req.user.
Basically it does this: req.user = payload.sub; (with some other background stuff)
Then the req.user is available in the following functions e.g. clients.update, but not in clients.clientByID.
I know I could execute users.ensureAuthenticated in clients.clientByID again, but this would execute the code twice and be extra load on the server, right? I guess there must be another way, but I couldn't find anything in the documentation of express.
I'd like to know how I can access the req.user in clients.clientByID without executing the code in users.ensureAuthenticated twice.
Based on your question, I assume you would like to execute users.ensureAuthenticated before clients.clientByID is executed. This can be achieved by using the app.use functionality. app.use handlers will get executed before the app.param and app.route handlers.
For example:
var express = require('express');
var app = express();
app.use('/user', function(req, res, next) {
console.log('First! Time to do some authentication!');
next();
});
app.param('id', function(req, res, next, id) {
console.log('Second! Now we can lookup the actual user.');
next();
});
app.get('/user/:id', function(req, res, next) {
console.log('Third! Here we do all our other stuff.');
next();
});
app.listen(3000, function() {
});

Categories