Nodejs with ExpressJS including external js code files for use - javascript

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

Why is my module function returning undefined in node.js? [duplicate]

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
}
})
}

TypeError: bcrypt.checkPassword is not a function

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.

How to open a new link with a request using Express and AngularJS

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();
});
});
});

Node.js Synchronous call on passport local signup

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
}
});

Node.js Mongoose static function not getting called

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
});

Categories