learning NodeJS here... I have this very basic "class" file I put into an external JS file. How do I make this available for all my routing files and or other external js files(that i also like to load) see?
/classes/music/usermanager.js
function User(){
this.email = "";
this.password = "";
this.userid = "";
}
function UserManager()
{
this.user = new User();
}
UserManager.prototype.login = new function (email, password){
var db = new DbManager();
db.Open();
params = {
$email : email,
$password : password
}
db.serialize(function(){
db.get("SELECT * FROM Users WHERE email = $email and password = $password", params, function(err,row) {
if (!err && row) {
//log in passed
this.user.userid = row.user.id;
this.user.email = row.user.email;
this.user.password = row.user.password;
return this.user;
}
else if (!err) {
//log in failed log event
return null;
}
else {
//error happened through out an event to log the error
return null;
}
});
});
}
/config/strategies/local.strategy.js example of how I would be using it in another file.
var passport = require('passport');
LocalStrategy = require('passport-local').Strategy;
module.exports = function () {
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (email, password, done) {
//vadliating user here
var userManager = new UserManager();
var user = userManager.login(email, password);
done(null, user);
}));
};
I tried doing something like this in my app.js file and it is barfing on compiling stating "throw new TypeError('app.use() requires middleware functions');". I could of sworn I read somewhere you could do that but now can't find the resource.
/asp.js
/*load external js library files for application use*/
app.use ("./classes/music/:path*");
Have a feeling i am missing a basic a understanding here still when trying to organize a nodejs/expressjs project.
Your actually using the answer in one of your examples. You make modules available by using the module.exports = whatever;. Meaning that you can export anything a string, an object, or a "class". So you could export UserManager by adding this to the end of the file (or really anywhere).
module.exports = UserManager;
and require it in another filer by using its relative file path. So if its in the same directory.
var UserManager = require('./usermanager.js');
So for the local.strategy.js file to require UserManager it would look like: (if you filepaths are all in the same root directory)
var UserManager = require('../../classes/music/usermanager.js');
/classes/music/usermanager.js
// Working for me, try it, hope this may help you
var model = module.exports;
function User() {
this.email = "";
this.password = "";
this.userid = "";
}
function UserManager() {
this.user = new User();
}
UserManager.prototype.login = function(email, password) {
var db = new DbManager();
db.Open();
params = {
$email : email,
$password : password
}
db.serialize(function(){
db.get("SELECT * FROM Users WHERE email = $email and password = $password", params, function(err,row) {
if (!err && row) {
//log in passed
this.user.userid = row.user.id;
this.user.email = row.user.email;
this.user.password = row.user.password;
return this.user;
}
else if (!err) {
//log in failed log event
return null;
}
else {
//error happened through out an event to log the error
return null;
}
});
});
};
model.login = function (email, password){
var usrmng = new UserManager();
return usrmng.login(email, password);
};
/config/strategies/local.strategy.js
var usermanager = require('./usermanager'); // path to ur file
var passport = require('passport');
LocalStrategy = require('passport-local').Strategy;
module.exports = function () {
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (email, password, done) {
//vadliating user here
//var userManager = new UserManager();
var use = usermanager.login(email, password);
done(null, user);
}));
};
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
So, I wanted to move all my mysql query functions to another file and import it as a module, but I'm having trouble in that the function is returning undefined.
index.js:
const express = require('express')
const https = require('https');
const fs = require('fs');
const dbx = require('./databaseconn');
var options = {
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/cert.pem'),
ca: fs.readFileSync('/etc/letsencrypt/live/example.com/chain.pem')
};
const app = express();
app.use(express.json());
app.use(function(req,res,next) {
if (req.body.action) {
switch (req.body.action) {
case "login":
var user = req.body.username;
var pass = req.body.password;
console.log(dbx.checklogin(user, pass)); // This prints undefined
break;
default:
break;
}
}
});
https.createServer(options,app).listen(8000);
databaseconn.js:
const mysql = require('mysql');
exports.checklogin = function(username, password) {
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'xxxxxxxxxxxxxx',
database : 'users',
});
connection.query('select * from logins where username = ? and password = ?;',
[
username,
password
], function (err, rows, fields) {
if (err) throw err;
if (!rows.length) {
console.log('0');
return {"success":0};
} else {
console.log('1'); // THIS PRINTS
return {"success":1}; // So this should return the JSON
}
})
}
So I see a "1" from the console.log in the databaseconn.js, but the console.log in the index.js file is printing undefined. What am I doing wrong? I also did a super barebones test that works fine so I can't see the difference.
test.js:
const express = require('express');
const test2 = require('./test2');
var t = test2.test();
console.log(t);
test2.js:
exports.test = function() {
return {"success":1};
}
console.log statement inside index.js module prints undefined because checklogin function inside databaseconn.js module does not return anything ({"success":1} is the return value of the inner anonymous function inside checklogin, but it is not a return value of checklogin itself).
Should you want to handle query result inside index.js module, you can pass a callback from index.js to databaseconn.js module, it may look like as follows:
index.js:
app.use(function(req, res, next) {
if (req.body.action) {
switch (req.body.action) {
case "login":
var user = req.body.username;
var pass = req.body.password;
dbx.checklogin(user, pass, function(err, rows, fields) {
console.log('Here you can handle the query result')
});
break;
default:
break;
}
}
});
databaseconn.js:
exports.checklogin = function(username, password, callback) {
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'xxxxxxxxxxxxxx',
database : 'users',
});
connection.query('select * from logins where username = ? and password = ?;',
[
username,
password
], callback)
}
It looks like you're returning {"success":1} from connection.query but the checklogin function itself isn't returning anything?
Try
const mysql = require('mysql');
exports.checklogin = function(username, password) {
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'xxxxxxxxxxxxxx',
database : 'users',
});
return connection.query('select * from logins where username = ? and password = ?;',
[
username,
password
], function (err, rows, fields) {
if (err) throw err;
if (!rows.length) {
console.log('0');
return {"success":0};
} else {
console.log('1'); // THIS PRINTS
return {"success":1}; // So this should return the JSON
}
})
}
I want to check password when users log in but there is an error message "TypeError: bcrypt.checkPassword is not a function".
Here are my code and I don't understand why bcrypt.checkPassword isn't a function.
[bcrypt.js]
var checkPassword = function(textEnteredInLoginForm, hashedPasswordFromDatabase) {
return new Promise(function(resolve, reject) {
bcrypt.compare(textEnteredInLoginForm, hashedPasswordFromDatabase, function(err, doesMatch){
if (err) {
reject(err);
}
console.log(doesMatch);
resolve(doesMatch);
});
});
};
module.exports.checkPassword = checkPassword;
[db.js]
var bcrypt = require('bcrypt');
module.exports.login = function(email, password){
var hashedPasswordFromDatabase;
var query = `SELECT * FROM users WHERE email ='{$req.body.email}'`;
db.query(query).then(function(data){
return hashedPasswordFromDatabase = data[0].password;
console.log("hashedPasswordFromDatabase : "+hashedPasswordFromDatabase);
});
return bcrypt.checkPassword(password).then(function(password, hashedPasswordFromDatabase){
var query = 'SELECT * FROM users';
return db.query(query).then(function(results){
return results.rows;
});
});
};
[ router.js ]
var express = require('express');
var cookieSession = require('cookie-session');
var db = require('../configure/db');
var bcrypt = require('../public/js/bcrypt');
var router = express.Router();
router.route('/login')
.get(function(req,res) {
res.render('login'); // url -> /login
})
.post(function(req,res){
db.login(req.body.email, req.body.password)
.then(function(data){
res.redirect('/petition'); // login -> petition
}).catch(function(error){
console.log(error);
res.render('error');
});
});
You made a file called bcrypt.js and are using the npm package bcrypt.
To use the package, like you would need to do in bcrypt.js, you would
require('bcrypt') //no path searches node_modules
To use the file you created, like you want to do db.js, you need to include your file
require('./bcrypt.js') //relative paths indicate local files
I'd suggest naming your file something different so you do not confuse the two.
I'm making a login script in Node, using a MEAN stack. Currently I can search the database and find the user. However, after I find the user, I'm trying to open a link to the index page, but when my code executes nothing happens. Does anyone know how to open links through a route?
client.js
var app = angular.module('myApp',[]);
app.controller('loginController',function($scope,$http) {
$scope.login = function(username,password) {
var objectJson = {'username':username,'password':password};
$http.post('/loginRequest',objectJson).success(function(response) {
console.log("response: "+response);
});
};
});
server.js
// Listen for Seach collection request
router.post('/loginRequest', function (req, res, next) {
var databaseName = "DB", collection = "Accounts";
var username = req.body.username, password = req.body.password;
var db = new Db(databaseName, new Server('localhost', 27017));
db.open(function (err, db) {
//var cursor = db.collection(collection).find( { "username":username,"password": password } );
// cannot apply cursor methods to the result of findOne() because a single document is returned.
db.collection(collection).findOne({ "username": username, "password": password }, function (err, doc) {
assert.equal(null, err);
if (doc != null) {
console.log("Found");
res.render('index', { title: 'Home Page', message: 'Message'});
}
db.close();
});
});
});
That's a AJAX call, you need to respond with a JSON but you are using res.render() that send a HTML.
angular:
var app = angular.module('myApp', []);
app.controller('loginController', function($scope, $http) {
$scope.login = function(username, password) {
var objectJson = {
'username': username,
'password': password
};
$http.post('/loginRequest', objectJson).success(function(response) {
location.href = '/';
}, function () {
alert('Invalid credentials');
});
};
});
node:
// Listen for Seach collection request
router.post('/loginRequest', function(req, res, next) {
var databaseName = "DB";
var collection = "Accounts";
var username = req.body.username;
var password = req.body.password;
var db = new Db(databaseName, new Server('localhost', 27017));
db.open(function(err, db) {
db.collection(collection).findOne({
"username": username,
"password": password
}, function(err, doc) {
if(err) {
throw err;
}
if (doc) {
// Here also you need to set logged state in req.session
// https://github.com/expressjs/session
res.json(doc);
} else {
res.status(400).json();
}
db.close();
});
});
});
I've been trying to get along with Node.js and I'm struggling to learn a few core things. My problem is in passport I dont know how to make a synchronous call. What I want is: If there is a user with the signup email already, I dont want to create it, ill throw a flash message, otherwise i'll create the user. I'm not sure how to only create the user after the check up for the email uniqueness. I tried it with return true/false in a if statement but it just doesn't seem right.
I adapted my code from scotch.io's passport tutorial.
// passport.js
// load all the things we need
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var User = require('../app/models/user');
// expose this function to our app using module.exports
module.exports = function(passport) {
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
if(!User.isEmailInUse(req)){
var newUser = {};
//create the user
User.createUser(req, newUser),
function (){
console.log('function ception ' + newUser)
if(newUser){
return done(null, newUser, req.flash('signupMessage', 'Great success!'));
}else{
return done(null, false, req.flash('signupMessage', 'An error has occurred.'));
}
};
console.log('what now?');
}else{
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}
}));
};
// user.js
var mysql = require('../../config/database.js').mysql;
var bcrypt = require('bcrypt-nodejs');
// Create user.
module.exports.createUser = function(req, res){
var input = JSON.parse(JSON.stringify(req.body));
var salt = bcrypt.genSaltSync(10);
var currentdate = new Date();
var datetime = currentdate.getFullYear() + "/"
+ (currentdate.getMonth()+1) + "/"
+ currentdate.getDate() + " "
+ currentdate.getHours() + ":"
+ currentdate.getMinutes() + ":"
+ currentdate.getSeconds();
// create the user
var newUserMysql = {
email: input.email,
password: bcrypt.hashSync(input.password, salt, null), // use the generateHash function in our user model
isActive: 1,
createdAt: datetime
};
var insertQuery = "INSERT INTO tUsers ( usrEmail, usrPassword, usrIsActive, usrCreatedAt ) values (?,?, ?, ?)";
console.log('about to run insert into');
mysql.query(insertQuery,[newUserMysql.email, newUserMysql.password, newUserMysql.isActive, newUserMysql.createdAt],function(err, rows) {
if(!err){
newUserMysql.id = rows.insertId;
console.log('returning user');
res = newUserMysql;
}else{
console.log(err);
res = null;
}
});
};
module.exports.isEmailInUse = function(req){
var input = JSON.parse(JSON.stringify(req.body));
var selectQuery = "SELECT * FROM tUsers WHERE usrEmail = ?";
var query = mysql.query(selectQuery, [input.email], function(err, rows, fields) {
console.log(query.sql);
if (!err){
if(rows > 0){
return true;
}
console.log('The solution is: ', rows);
return false;
}
else
{
console.log('Error while performing Query -> ' + err);
return false;
}
});
};
You need to return a callback in the function isEmailInUse.
Inside this function you are calling the mysql.query that is runing an asyn call to the database.
change the function isEmailInUser to:
module.exports.isEmailInUse = function(req, callback){
var input = JSON.parse(JSON.stringify(req.body));
var selectQuery = "SELECT * FROM tUsers WHERE usrEmail = ?";
var query = mysql.query(selectQuery, [input.email], function(err, rows, fields) {
console.log(query.sql);
if (!err){
if(rows > 0){
return callback(null, true);
}
console.log('The solution is: ', rows);
return callback(null, false);
}
else {
console.log('Error while performing Query -> ' + err);
return callback(err, false);
}
});
};
And to use it:
IsEmailInUser(req, function(err, inUse){
if(isUse){
//create code
}
else {
//send error to user
}
});
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
});