req.login is not logging the user - javascript

What I am trying to do is use ajax to send a post request to the server, and make sure that post request does not refresh the page (using e.preventDefault). On the server I want to check if the username or email is taken and if it is not taken, then automatically log the user in and then refresh the page. The issue is when I call req.login and submit the data to be logged in it doesn't seem to be working but the page still refreshes. Any ideas?
app.post('/signup', function (req, res) {
var userDetails = User({
username: req.body.username,
email: req.body.email,
password: bcrypt.hashSync(req.body.password1, bcrypt.genSaltSync(10))
});
User.findOne({
$or: [{
'username': req.body.username
}, {
'email': req.body.email
}]
}, function (err, user) {
if (user) {
if (allClients.indexOf(req.body.socket)) {
if (user.username === req.body.username) {
io.to(req.body.socket).emit('userInfo', 'That username is already in use.');
} else {
}
if (user.email === req.body.email) {
io.to(req.body.socket).emit('userInfo', 'That email is already in use.');
} else {
}
} else {
console.log('timeout error 822')
}
} else {
req.login(userDetails, function (err) {
if (!err) {
userDetails.save(function (err) {
if (err) throw err;
res.redirect('/');
});
} else {
console.log(err)
}
})
}
if (err) {
return done(err);
}
});
});
Here is where I make the ajax post request. As you can see I am preventing the form submit to refresh the page, but if the form is succesful it will submit.
$("#form1").submit(function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: '/signup',
data: $(this).serialize(),
success: function(data)
{
window.location.reload(true);
}
});
});

I believe your 'already taken' messages are considered success by your API.
You can either throw an error on those cases and catch with $.ajax or set a different response and read data on success.

Related

How to pass jwt token from controller to router using NodeJS

Hello developers the question is simple,
I have generated a jwt token in my Login function using the jwt.sign(), and I have Model/Controller/Router Architecture,
so the question is : How can I pass the generated token from the Login controller function to the router.
I've tried many times to assign the token to a const variable to send it throw an object and send it to the router files, but when I go out from the jwt.sign() function it shows me that is undefined.
PS : I'am just using NodeJS and fastify in the backend and send http request with Postman am not using any framework in the front-end
There is some code than can help you to understand my situation :
UserRouter.js: (Login route) :
{
method: "POST",
url: "/api/login",
handler: (req, res) => {
UserController.login(req.body.email, req.body.password)
.then(result => {
//res.header("Access-Control-Allow-Origin", URL);
if (result.statusCode == 200) {
res.send({
status: 200,
error: null,
response: result.Message
//token: result.token
});
} else if (result.statusCode == 401) {
res.send(
JSON.stringify({
status: 401,
error: null,
response: result.Message
})
);
}
})
.catch(err => {
//res.header("Access-Control-Allow-Origin", URL);
res.send(JSON.stringify({ status: 300, error: err, response: null }));
});
}
}
User Controller :
exports.login = async (user_email, password) => {
try {
console.log("Login into API");
const email = user_email.toLowerCase();
const user = await User.findOne({ email });
if (user) {
console.log(" Hashed Passwd ", user.password);
console.log("User Passwd", password);
let result = await bcrypt.compareSync(password, user.password);
if (result) {
// Tryed also with const = await jwt.sign()
jwt.sign({ user }, "secretkey", (err, token) => {
if (err) throw err;
console.log("The Token is", token);
});
return {
Message: "Login success",
statusCode: 200
//token: token
};
} else {
return { Message: "Incorrect password", statusCode: 401 };
}
} else {
return { Message: "ERROR" };
}
} catch (err) {
throw boom.boomify(err);
}
};
if you look at the package readme, you'll find jwt.sign returns nothing when a callback is provided.
So what you should do is:
const token = jwt.sign({ user }, "secretkey");
That would make the library work synchronously and return the token.

I need to send an alert back to the user when there is no records found

This is my post request from nodejs server
app.post('/api/users', urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
console.log(req.body);
var data = req.body;
db.collection('users').findOne({
username: data.username
}, (err, result) => {
if (result === null) {
db.collection('users').insertOne(data, function (err) {
if (err) throw err;
console.log("Record inserted!");
res.status(200).send("recordInserted");
})
} else {
console.log("Already exists");
res.status(500).send("userExists");
}
})
})
This is my ajax request
$('#signupForm').on('submit', function () {
var userData = {
fullName: $("#fullName").val(),
username: $("#username").val(),
password: $("#password").val(),
email: $("#email").val()
};
$.ajax({
type: "post",
data: userData,
dataType: "text",
url: "/api/users",
function (data, status) {
if(data== 'recordInserted'){
alert("Recors inserted");
console.log("Inserted \n" + data +"\n" + status);
}
else if(data == 'userExists') {
alert("User exists");
console.log(data + "\n " + status);
}
}
});
});
I cant send back the response to the ajax request and because of that the page doesn't reload or show an error if the user already exists
As a first order of business, the preferred way for awhile now to handle responses in AJAX has been to utilize deferred objects.
let request = $.ajax({url: 'google.com', type:'get'});
request.done(function(response){
// handle response
});
Beyond that, your back-end looks to be fine.
Although!
I would highly recommend changing how you go about error handling on the server-side. If the server throws an error, the client will be left hanging until they timeout. Its best to alert the client that an error has occurred, as well.
use of e.preventDefault(); method will stop the page from being reload. you can copy paste the code
$('#signupForm').on('submit', funfunction(e) {
e.preventDefault();
let userData = {
fullName: $("#fullName").val(),
username: $("#username").val(),
password: $("#password").val(),
email: $("#email").val()
};
$.ajax({
type: "post",
data: userData,
dataType: "text",
url: "/api/users",
function (data, status) {
if(data== 'recordInserted'){
alert("Recors inserted");
console.log("Inserted \n" + data +"\n" + status);
}
else if(data == 'userExists') {
alert("User exists");
console.log(data + "\n " + status);
}
}
});
});

MeteorJS call rest api server side

Now i call rest API with:
Template.accedi.events({
'submit #form-login'(e) {
e.preventDefault();
var data = {
'username': $("[name=login_username]").val(),
'password': $("[name=login_password]").val()
};
var url = api_url + "/Token";
HTTP.call('POST', url, {
params: {
'grant_type': 'password',
'username': data.username,
'password': data.password
}
}, (error, result) => {
if (!error) {
Session.set('userData', JSON.stringify(result.data));
localStorage.setItem('userData', JSON.stringify(result.data))
Router.go('/');
}
}
}
})
This call rest api client side.
I need to call the api server side... there is a method?
You should create method which is then called from your client code. Something like below should works in your case.
Methods have to be defined in code which is loaded on the client and server.
Meteor.methods({
'login.token'({ username, password }) {
try {
let request = HTTP.call('POST', 'https://example.com', {
params: {
'grant_type': 'password',
'username': username,
'password': password
}
})
// You might want to process, validate etc. request response before return it to the client.
return request
} catch (err) {
throw new Meteor.Error(500, 'There was an error processing your request')
}
}
})
Your client code might looks similiar to this
Template.accedi.events({
'submit #form-login'(e) {
e.preventDefault();
var data = {
'username': $("[name=login_username]").val(),
'password': $("[name=login_password]").val()
};
Meteor.call('login.token', {
username: data.username,
password: data.password
}, (err, res) => {
if (err) {
console.log(err)
} else {
Session.set('userData', JSON.stringify(res.data));
localStorage.setItem('userData', JSON.stringify(res.data))
Router.go('/');
}
})
}
})
You can find more about methods in Meteor guide at this page https://guide.meteor.com/methods.html

How to implement this in node.js?

I have the following request handler that would sign in a user with Firebase. Upon successful login, I'd like to redirect the user to another page.
Would I change window.location to another page within the (document).ready() javascript function? Or would I implement the change here, with a res.redirect (that I did try) but nothing happened, I just got back a status code within the console.
app.post('/api/sign-in', function (req, res, next) {
firebase.auth().signInWithEmailAndPassword(req.body.email, req.body.password).then(function (user) {
console.log('a new user has signed in! their e-mail address: ' + user.email + ' | User ID: ' + user.uid)
}).catch(function (error) {
console.log(error)
})
})
Call:
$("#sign-in").on('click', function (event) {
event.preventDefault()
$.ajax({
url: '/api/sign-in',
method: 'POST',
data: {
email: $('#email').val(),
password: $('#password').val()
}
});
});
Like George said, if you are doing a ajax post it won't redirect.
Maybe something like this could help you:
app.post('/api/sign-in', function (req, res, next) {
firebase.auth().signInWithEmailAndPassword(req.body.email, req.body.password).then(function (user) {
res.send({ redirect: '/profile' })
}).catch(function (error) {
console.log(error)
})})
Javascript:
$(document).ready(function () {
$('#sign-in').click(function () {
event.preventDefault()
$.ajax({
url: '/api/sign-in',
method: 'POST',
dataType: 'json',
success: function (data, textStatus, jqXHR) {
if (typeof data.redirect === 'string') {
window.location = data.redirect;
}
}
});
});
});
Hope it can be useful.

Only success handler is called - AngularJS

Below is a part of my /authenticate method, which finds a user with the given username and password.
User.findOne({
username: req.body.username,
password: req.body.password
}, function(err, user) {
if (err) {
res.json({
type: false,
"status": "401",
"data": "Incorrect email/password"
});
} else {
if (user) {
console.log("token");
res.json(generateToken(user));
} else {
res.json({
type: false,
"status": "401",
"data": "Incorrect email/password"
});
}
}
});
When there is no such username or password, by condition inside if(err) never fires.
Secondly, when i call this method from my angular-js code, regardless of success/error only success is called.
login: function (username, password) {
return $http.post('http://localhost:8888/login', {
username: username,
password: password
});
}
My Controller calling code:
AutheService.login(username, password).success(function(response) {
console.log(response); // error message as well as success comes here
}).error(function(data, status){
console.log(data, status);
})
You need to respond with an actual error code on your server-side. I'm assuming you're using expressJS and after looking at their docs, you can chain your response like res.status(401).json(...):
User.findOne({
username: req.body.username,
password: req.body.password
}, function(err, user) {
if (err) {
res.status(401).json({
type: false,
"status": "401",
"data": "Incorrect email/password"
});
} else {
if (user) {
console.log("token");
res.json(generateToken(user));
} else {
res.status(401).json({
type: false,
"status": "401",
"data": "Incorrect email/password"
});
}
}
});

Categories