I'm making a simple webapp with facebook login.
If the facebook login button on my page is clicked,
FB.api(
'/me',
'GET',
{"fields":"id,name,birthday,gender"},
function(response) {
$.post('fb_login', response, "json");
}
);
is called, and a router handles '/fb_login' request; in the router the server checks the id of json object is already in its DB. If not, res.render('signup', ...) should be called.
However it didn't work. I already checked that res.render() was called, but the page 'signup.jade' didn't show up.
Here is my source code of router.
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '1012'
});
/* GET home page. */
router.post('/', function(req, res, next) {
var userid = req.body.id;
if (userid) {
pool.getConnection(function(err, connection) {
if (err) {
console.error('DB Connection error!!');
return;
}
console.log('DB Connection Success!!');
connection.query('use vasket');
connection.query('select count(*) result from user where userID=?',
[userid], function(err, result, field) {
var isAlreadyUser = result[0].result;
console.log(isAlreadyUser);
if (isAlreadyUser == 1) {
req.session.userid = userid;
res.redirect('/');
res.end();
console.log('DB FB Login Success!!');
connection.release();
}
else {
connection.release();
console.log('FIRST TIME!');
//This method was called, but the page rendered didn't
res.render('signup', {id: req.body.id, name: req.body.name, birthday: req.body.birthday, gender: req.body.gender});
}
});
});
} else {
res.redirect('/');
res.end();
}
How can I fix it?
To help debugging maybe you can modify your code like that :
// ... your code before
else {
connection.release();
console.log('FIRST TIME!');
console.log(req.body);
//This method was called, but the page rendered didn't
res.render(
'signup',
{
id : req.body.id,
name : req.body.name,
birthday: req.body.birthday,
gender : req.body.gender
} ,
function(err, html){
if(err) console.log(err);
console.log(html);
//res.send(html);
// trying same but forcing status
res.status(200).send(html);
}
);
}
});
});
} else {
res.redirect('/');
res.end();
}
This is an older question, but it's still in need of a solid answer. I had the exact same problem, but I think I've figured it out.
If the server's returning the proper response, that's not where your problem lies. jQuery (in the browser) will render the response, but you have to tell it to do so.
Here's what I had that was responding properly but not rendering:
$("#getsome").click(function() {
$.get("/task/create");
});
And here's how I got it to render:
$("#getsome").click(function() {
$.get("/task/create", function( data ) {
document.write(data);
});
});
Note that you may not need to replace the entire DOM like I'm doing.
References:
Replacing the entire
DOM
jQuery.get
Related
we're working on a project for our Programming-Course. We're doing a very small social media platform, where you can register, login, create a profile, view events and log out.
So I set the session variable for logging in, but I also want that people who register are instantly logged in and get redirected to the profile-site. So I have to set another session into the registration app.post I guess, but I have absolutly no Idea how to do this (because I'm a bloody beginner)... Can anybody help? This is the code so far:
//------------Sessionvariables---------------//
app.get('/', requiresLogin, function(req, res) {
res.render('home', {
'username': req.session.user.name
});
});
app.post('/sendLogin', function(req, res) {
//in Datenbank gucken
const user = req.body["username"];
const password = req.body["password"];
db.get(`SELECT * FROM users WHERE username='${user}'`, function(err, row) {
if (row != undefined) {
if(password == row.password) {
req.session['user'] = user;
res.redirect('/home');
}else{
res.redirect('/loginerror');
}
}else{
res.redirect('/loginerror');
}
if(err){
console.error(err.message);
}
});
});
app.get('/logout', function(req, res){
req.session.destroy(function (err) {
if (err) return next(err)
req.session = null;
res.redirect('/start-login');
});
});
// Registration
app.post('/registration', function(req, res) {
const { email, password, username, domicile } = req.body;
// validation
db.run(`INSERT INTO users(email,password,username,domicile) VALUES(?, ?, ?, ?)`, [email, password, username, domicile], function(err) {
if (err) {
return console.log(err.message);
}
return res.redirect('/edit_profile');
});
});
I know that I have to write the session into the app.post /registration - Part, but I don't know how to write it. I'm using Node js, Express and sqlite3...
Thank you!!
Why not just do:
// Registration
app.post('/registration', function(req, res) {
const { email, password, username, domicile } = req.body;
// validation
db.run(`INSERT INTO users(email,password,username,domicile) VALUES(?, ?, ?, ?)`, [email, password, username, domicile], function(err) {
if (err) {
return console.log(err.message);
} else {
// Create the session / save any data you want here
req.session.user.name = username;
/* I would actually call somthing like: createSession(req)
dedicated function that nicely creates the session */
// Redirect to home just like you do after successful login
res.redirect('/home'); // Redirect to home since user registered successfully
}
});
});
By the way always treat error before running other code logic i see you are treating errors at the end of code (in the app.post('/sendLogin',...) :
if(err){
console.error(err.message);
}
Write like this:
if(err){
console.error(err.message);
// and res.end() or similar if its in an express route
} else {
// Do safe stuff here
}
the best method i can suggest you is that after registration success set the user details in session and just redirect to your home page
my problem is that my session is undefined as in new layers as even after "if" where the session value was set.
/*******************************************/
/**/ var express = require('express'),
/**/ cookieParser = require('cookie-parser'),
/**/ session = require('express-session'),
/**/ bodyParser = require('body-parser'),
/**/ ejs = require('ejs'),
/**/ mysql = require('mysql'),
/**/ md5 = require('md5');
/*******************************************/
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'samurai'
});
connection.connect(function(error) {
if(error) {
console.log("There is a problem with connection to the database.");
return;
}
console.log("Connected with a database.");
});
app.use(cookieParser());
app.use(session({
secret: 'test session',
resave: false,
saveUninitialized: true
}));
var sess;
Here my session is undefined (first I go to the '/sign' address):
app.get('/', function(req, res) {
sess = req.session;
console.log("sesja = "+sess.login); <--------------- undefined
if(sess.login) {
res.render('indexo');
} else {
res.render('index');
}
});
app.post('/sign', function(req, res, next) {
sess=req.session;
var query = 'SELECT * FROM ?? where ??=? AND ??=?';
var table = ["users", "name", req.body.login, "password", md5(req.body.password)];
query = mysql.format(query, table);
connection.query(query, function(err, rows) {
if(err) {
console.log(err);
return;
} else if(rows.length > 0) {
console.log("You have been sucessfully logged in.");
sess.login = req.body.login;
console.log(sess.login); <------------ works fine
} else {
console.log("The name or password is incorrect.");
}
});
console.log(sess.login); <---------------- here again undefined
res.end();
});
The problem is only in sessions case because if I create other global variable next to "var sess;" (for example var test;) and set for the variable a value in the "if" in '/sign" layer, then the "test" would be visible in the other layers and after that "if".
The final question: Why the session.login is invisible after the "if" and in other layer? How to set it properly? Have you some tips for me with sessions creating?
Thank you guys for your time and help.
Setting global variables from an http request is an evil thing to do and is fraught with problems. First off, your server can have multiple requests in flight at the same time from different users. Using globals from requests like this means that different requests will "stomp" on each others globals and all sorts of chaos and bugs will ensue.
Stop using globals at all for session information. If you need to communicate session info to other functions, then pass it to them as function arguments.
And, secondly you MUST understand how async operations work in node.js to have any chance of programming successfully in node.js. You are making several mistakes with your asynchronous programming and that's one main reason why variables aren't set where you think they should be.
In this code:
app.post('/sign', function(req, res, next) {
sess=req.session;
var query = 'SELECT * FROM ?? where ??=? AND ??=?';
var table = ["users", "name", req.body.login, "password", md5(req.body.password)];
query = mysql.format(query, table);
connection.query(query, function(err, rows) {
if(err) {
console.log(err);
return;
} else if(rows.length > 0) {
console.log("You have been sucessfully logged in.");
sess.login = req.body.login;
console.log(sess.login); <------------ works fine
} else {
console.log("The name or password is incorrect.");
}
});
// this is executed BEFORE the connection.query() callback is called
console.log(sess.login); <---------------- here again undefined
res.end();
});
connection.query() is asynchronous. T'hat means that it calls its callback sometime in the future. Thus your console.log(sess.login); at the end of your request is happening BEFORE the callback has ever been called.
You aren't specific about exactly what you want to happen in all the cases in your query, but here's an outline for how the code could work:
app.post('/sign', function(req, res, next) {
var query = 'SELECT * FROM ?? where ??=? AND ??=?';
var table = ["users", "name", req.body.login, "password", md5(req.body.password)];
query = mysql.format(query, table);
connection.query(query, function(err, rows) {
if(err) {
console.log(err);
res.end("Query error");
} else if(rows.length > 0) {
res.end("Logged in successfully");
} else {
res.end("The name or password is incorrect.");
}
});
});
You may find this general answer on asynchronous responses useful: How do I return the response from an asynchronous call?
I am trying to inject a session value into the request so i can use it on different situation on my app. What i am doing is calling a function by giving the id to search for a user into database and return me the name of that specific user. The issue i am facing is when i try to declare the session, it looks like is not working or the callback is not letting this new value out.
Let me show you my code example for an better idea:
The middleware
var express = require('express');
var session = require('express-session');
var router = express.Router();
var userSession = require('../../helpers/user/userSession');
router.use(function(req, res, next){
if (req.method == "GET") {
if (!req.user) {
req.session.username = '';
}else{
var sess = userSession.findUser(req.user, function(err, user){
if (user) {
console.log(user); //It contains the value i need
req.session.username = user; // Supposed to inject the user value to the username session variable.
};
console.log(req.session.username); //it works until here, out of this function not anymore.
});
console.log(req.session.username); //the req.session.username is empty now
};
return next();
}else{
return next();
}
});
Check if user exist
var mongoose = require('mongoose');
var User = mongoose.model('database')
module.exports = {
findUser: function(user, callback){
User.findOne({ 'unq_id' : user }, function(err, user){
if (err) {
console.log('Error: ' +err);
return callback(err, false);
};
if (user) {
//console.log(user);
return callback(null, user.user_collection.firstname);
}else{
return callback(err, false);
};
});
}
}
One idea is to give to that sess variable the value of user, but it appears very difficult since is asynchronous call. I am sure some of might have run into this issue.
How can i get around this? any suggestion will be much appreciated.
How about this?
router.use(function(req, res, next){
if (req.method == "GET") {
if (!req.user) {
req.session.username = '';
next();
} else {
userSession.findUser(req.user, function(err, user){
if (user) {
req.session.username = user;
};
next();
});
}
} else {
next();
}
});
That way it won't go to the next middleware until after the username has been retrieved.
Recently i've been trying to rewrite my node.js express app to be more in line with the mvc principle. I've also been trying to incorporate mongoose. I'm having a problem with calling the static functions on a mongoose model.
userSchema.statics.findDuplicates = function (cb) {
console.log("Duplicates called");
this.findOne({ email: this.email }, function(err, result){
if (err) throw err;
if (result) {
cb("A user with this email has already been created.");
} else {
cb("");
}
});
}
Now the problem is that i'm later exporting a model using this schema, so this is all contained in one file:
module.exports = mongoose.model('User', userSchema);
When i later call this inside a controller, (obviously requiring and initiating the model beforehand):
user.findDuplicates(function(result){
if (result) {
res.send("Selle e-mailiga kasutaja on juba loodud.");
console.log("Duplicates");
} else {
user.save();
res.send("Kasutaja loodud.");
console.log("User created with password.")
}
});
It just never gets called. Node tells me it accepted a post, but got a 500 internal server error, and the "Duplicates called" inside findDuplicates does not appear in the console. Something is very wrong here, and i do not know how to fix it.
EDIT: Full controller code:
var express = require('express');
var router = express.Router();
var User = require("../models/user.js");
router.get('/', function(req, res, next) {
res.render('users',{title: "Lisa kasutaja"});
});
router.post('/', function(req, res, next) {
var query = req.body;
var message = "";
console.log("Post recieved " + JSON.stringify(query));
if (query.password != query.repeatPassword){
res.send("Paroolid ei ole võrdsed.");
console.log("Passwords don't match");
} else {
var user = new User({
firstName: query.firstName,
lastName: query.lastName,
telephone: query.telephone,
email: query.email,
password: query.password
});
console.log("User created");
user.findDuplicates(function(result){
if (result) {
res.send("Selle e-mailiga kasutaja on juba loodud.");
console.log("Duplicates");
} else {
user.save();
res.send("Kasutaja loodud.");
console.log("User created with password.")
}
});
}
});
module.exports = router;
Your problem resides in the fact that you're calling a static method in an instance of a model, which is not correct. See the difference below:
// if you define a static method
userSchema.statics.findDuplicates = function (cb) {
// do your stuff
}
// you call it this way
var User = require("../models/user.js");
User.findDuplicates(function (result) {
// do your stuff
});
// if you define an instance method
userSchema.methods.findDuplicates = function (cb) {
// do your stuff
};
// you call it this way (on an instance of your model)
var User = require("../models/user.js");
var user = new User({
firstName: query.firstName,
lastName: query.lastName,
telephone: query.telephone,
email: query.email,
password: query.password
});
user.findDuplicates(function (result) {
// do your stuff
});
How can I log an end user into my single page application, and redirect them to the Single page application, using Backbone.js. Express.js and passport.js.
I have passport, mongo.db, express, and backbone all working on my application. However, upon successful login, I want to load up the single page, backbone js, web application. As of right now, I have the login system working fine. But when I go to redirect the user to the application, after successful login, for some reason it just redirects right back to the login page. I have used console log to make sure that there is nothing wrong with the login code on the server side and everything is working fine. The strange thing is that when I open chrome developer tools, and look at the headers and response, I'm getting the correct index page back, but it's not loading in the browser and the Url remains http://localhost:3000/login.
Here is the code that I suspect must somehow be the culprit:
See edit #2
I've tried both res.sendfile(__dirname + '/public/index.html'); and res.render('index', { user: req.user }); in my base ('/') route but neither of them seems to be loading the index.html. Note that public/index.html and the ejs index are essentially the same files. I started off having my entire app load up on the client side but now I'm trying to move the main index.html file over to the server side so that it can be password protected.
Please let me know if there is any questions at all that will help me better explain this problem, or if there is anymore code that you would like to see. I really want to get this thing figured out.
Edit As you can see with this screenshot of my browser, I have nothing more than simple form. When that form is submitted, I do get back the desired page in the response, but it's not loading up in the browser. I'm also getting a failed to load resource error in the console, but it's failing to load /login for some reason - even though I'm trying to load index.
Edit #2 As much as I hate to paste endless blocks of code, I think the only way to resolve this issue is to paste endless blocks of code.
So here is server.js in all it's glory - minus some of the api routes that are irrelevant:
var express = require('express')
, http = require('http')
, passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, bcrypt = require('bcrypt')
, SALT_WORK_FACTOR = 10
, mongoose = require('mongoose')
, path = require('path');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(3000);
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs-locals'));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use( express.errorHandler({ dumpExceptions: true, showStack: true }));
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
//Connect to database
var db = mongoose.connect( 'mongodb://localhost/attorneyapp' );
/*
|-------------------------------------------------------------------------------
| Schemas
|-------------------------------------------------------------------------------
*/
var userSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true},
});
// Bcrypt middleware
userSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if(err) return next(err);
bcrypt.hash(user.password, salt, function(err, hash) {
if(err) return next(err);
user.password = hash;
next();
});
});
});
// Password verification
userSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if(err) return cb(err);
cb(null, isMatch);
});
};
var Client = new mongoose.Schema({
first_name: String,
last_name: String,
status: String,
});
var Case = new mongoose.Schema({
case_name: String,
status: String,
});
/*
|-------------------------------------------------------------------------------
| Models
|-------------------------------------------------------------------------------
*/
var User = mongoose.model( 'User', userSchema );
var ClientModel = mongoose.model( 'Client', Client );
var CaseModel = mongoose.model( 'Case', Case );
// Seed a user
// var user = new User({ username: 'bob', email: 'bob#example.com', password: 'secret' });
// user.save(function(err) {
// if(err) {
// console.log(err);
// } else {
// console.log('user: ' + user.username + " saved.");
// }
// });
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object. In the real world, this would query a database;
// however, in this example we are using a baked-in set of users.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) {
console.log('error: ', err);
return done(err);
}
if (!user) {
console.log('Unknown user ', username);
return done(null, false, { message: 'Unknown user ' + username });
}
user.comparePassword(password, function(err, isMatch) {
if (err){
console.log('error: ', err);
return done(err);
}
if(isMatch) {
console.log('it is a match');
return done(null, user);
} else {
console.log('invalid password');
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
/*
|-------------------------------------------------------------------------------
| User
|-------------------------------------------------------------------------------
*/
// POST /login
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
//
// curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login
//
/***** This version has a problem with flash messages
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
*/
// POST /login
// This is an alternative implementation that uses a custom callback to
// acheive the same functionality.
app.get('/', function(req, res){
console.log('base router is being called');
// res.sendfile(__dirname + '/public/index.html');
res.render('index');
});
app.get('/login', function(req, res) {
return res.render('login');
});
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
console.log('NOT USER', info.message);
req.session.messages = [info.message];
return res.redirect('/login');
}
req.logIn(user, function(err) {
if (err) { return next(err); }
console.log('YES USER is loged in');
// return res.sendfile(__dirname + '/public/index.html');
return res.redirect('/');
});
})(req, res, next);
});
app.get('/users', function(req, res){
return User.find( function( err, users ) {
if( !err ) {
return res.send( users );
} else {
return console.log( err );
}
});
});
Also, not sure if this is relevant, but here is my directory and file structure.
Try to return empty value. (undefined, actually)
I mean
res.redirect('/');
return;
instead of
return res.redirect('/');
And don't use res.render('index'... and res.sendfile(... in login! It response data from index.html to client on /login page!