How can I access app.locals within User model file? - node.js

I've created a file to hold some application wide configuration using app.locals. That config file looks like this:
config/vars.js
// App wide variables
module.exports = function (app) {
app.locals.accessLevels = [
{
"levelName" : "Basic",
"scrapes" : 3
},
{
"levelName" : "Pro",
"scrapes" : 10
},
{
"levelName" : "Ultimate",
"scrapes" : 99999
}
];
}
I want to access the app.locals.accessLevels array within my user's model which is here:
app/models/user.js
var userSchema = mongoose.Schema({
local : {
firstName : String,
lastName : String
// more stuff, simplified here for the question
}
});
userSchema.methods.remainingScrapes = function() {
// === >>> I need access to app.locals.accessLevels here
var today = new Date().yyyymmdd();
var scrapes = this.local.scrapes;
if (scrapes.length > 0) {
scrapes.forEach(function(item, i) {
if (today === item.date.yyyymmdd()) {
return item.count;
}
});
}
}
module.exports = mongoose.model('User', userSchema);
Then, there is also my existing code to consider where I'm accessing the User model (e.g. routes.js) because if I change something in the user model file, I don't want it to break my routes.js file...
** app/routes.js **
// I have simplified this file and removed excess code, but the function below
// is using the User model, so I have kept it in to demonstrate what code I have
var User = require('../app/models/user');
module.exports = function(app, passport) {
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated()) {
return next();
}
// automatically login admin
else if (app.locals.env == "development") {
User.findOne({ 'local.email' : 'anthony.hull#gmail.com' }, function (err, user) {
if (err) {
throw err;
} else {
console.log("login", "defaulting to admin user log in");
// assign user to req.user with passport's login method
req.login(user, function(err) {
if (err) {return next(err); }
return next(null, user);
});
}
});
}
else {
res.redirect('/login');
}
}
}

Related

Mongoose findOne function is not working with authentication

I am working on a model here:
// user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
// Define collection and schema for Users
let User = new Schema(
{
firstName: String,
lastName: String,
emailaddress: String,
password: String,
},
{
collection: 'users'
}
);
// authenticate input against database documents
User.statics.authenticate = ((emailaddress, password, callback) => {
User.findOne({ emailaddress: emailaddress })
.exec(function(error, user){
if(error){
return callback(error)
} else if (!user){
console.log('User not found!');
}
bycrypt.compare(password, user.password, function(err, result){
if(result === true){
return callback(null, user);
} else {
return callback();
}
})
})
});
module.exports = mongoose.model('User', User);
As you can see on my model I put the User.statics.authenticate on my codes to do some authentication. And then on my login.js route file:
const path = require('path');
const express = require('express');
const router = express.Router();
const db = require('../../database/index');
const axios = require('axios');
const User = require('../../database/models/user');
router.get('/', (req, res) => {
console.log('hi there this is working login get');
});
router.post('/', (req, res) => {
var emailaddress = req.body.emailaddress;
var password = req.body.password;
if( emailaddress && password ){
User.authenticate(emailaddress, password, function(err, user){
if(err || !user){
console.log('Wrong email or password!');
} else {
req.session.userId = user._id;
return res.redirect('/');
}
});
} else {
console.log('both fields are required...');
}
});
module.exports = router;
I called the function and then User.authenticate function and also I created the route for root w/c is the sample that I want to protect and redirect the user after login:
router.get('/', (req, res) => {
if(! req.session.userId ){
console.log('You are not authorized to view this page!');
}
User.findById(req.session.userId)
.exect((err, user) => {
if(err){
console.log(err)
} else {
res.redirect('/');
}
})
});
Upon clicking submit on my react form it returns this error:
TypeError: User.findOne is not a function
at Function.User.statics.authenticate (/Users/mac/Documents/monkeys/database/models/user.js:35:8)
I checked the Mongoose documentation and it seems I am using the right syntax.Any idea what am I doing wrong here? Please help! Sorry super beginner here!
PS. I've already installed and set up the basic express session too.
UPDATES:
I remove the arrow function from my call and use this.model.findOne but still get the typerror findOne is not a function
// authenticate input against database documents
User.statics.authenticate = function(emailaddress, password, callback){
this.model.findOne({ emailaddress: emailaddress })
.exec(function(error, user){
if(error){
return callback(error)
} else if (!user){
console.log('User not found!');
}
bycrypt.compare(password, user.password, function(err, result){
if(result === true){
return callback(null, user);
} else {
return callback();
}
})
})
};
findOne is a method on your User model, not your user model instance. It provides its async results to the caller via callback:
User.findOne({field:'value'}, function(err, doc) { ... });

Mongoose how to update an user info

I am having trouble making the #PUT method for my application. So far, I managed to make the #GET, #POST and #DELETE. So after doing some research, it turns out that the #PUT is a mixture of my #GET and #POST.
My #GET (by cuid) method
export function getUser(req, res) {
// just get the user information
User.findOne({ cuid: req.params.cuid }).exec((err, user) => {
if (err) {
return res.status(500).send(err);
}
return res.json({ user });
});
}
My #POST method
export function addUser(req, res) {
// Check for empty fields
if (!req.body.user.firstName || !req.body.user.lastName ||
!req.body.user.email || !req.body.user.password ||
!req.body.user.studentId) {
return res.status(403).end();
}
const newUser = new User(req.body.user);
// Let's sanitize inputs
newUser.firstName = sanitizeHtml(newUser.firstName);
newUser.lastName = sanitizeHtml(newUser.lastName);
newUser.studentId = sanitizeHtml(newUser.studentId);
newUser.email = sanitizeHtml(newUser.email);
newUser.password = sha512(newUser.password).toString('hex');
newUser.cuid = cuid();
newUser.save((err, saved) => {
if (err) {
return res.status(500).send(err);
}
return res.json({ user: saved });
});
}
The req.body.user will be the same in the #PUT method as in the addUser function on the #POST. In other words, the req.body.user will be something like { firstname: 'assa', lastName: 'nen', email: 'ed#aid.com', password: 'ddee', student: 112 }
My question is how would you modify the specific user (by cuid) information and save it to the db? In other words, how would you write the #PUT method
Try findOneAndUpdate
export function updateUser(req, res) {
var userId = req.body.userId;
var conditions = {
_id : userId
}
var update = {
firstName = sanitizeHtml(req.body.firstName );
lastName = sanitizeHtml(req.body.lastName);
studentId = sanitizeHtml(req.body.studentId);
email = sanitizeHtml(req.body.email);
password = sha512(req.body.password).toString('hex');
}
model.findOneAndUpdate(conditions,update,function(error,result){
if(error){
// handle error
}else{
console.log(result);
}
});
}

Mongodb findone query in node.js & express times out

I'm trying to find one user in a db where password and username matches. If I write the correct username and password everything works smoothly. But if I write the wrong password for instance I get a timeout after about one minute.
Any suggestions of how I could fix this?
exports.bsLogin = function(req, res) {
console.log('************ bslogin ************');
var body = req.body;
var username2 = body.username;
var password2 = body.password;
db.collection('users', function(err, collection) {
collection.findOne({username:username2, password:password2}, function(err, item) {
if (err) {
res.render('bslogin',
{ title : 'Hello', error : 'Username or Password is incorrect' }
);
return;
}
if (item) {
res.writeHead(302, {
'Location': '/backstageArea'
});
res.end();
}
});
});
};
It's timing out because no response is being given when there is neither an err nor an item.
Based on the current responses, the 1st if could probably be modified to handle both MongoDB errors and lack of items:
if (err || !item) {
res.render('bslogin',
{ title : 'Hello', error : 'Username or Password is incorrect' }
);
return;
}
Or, add an else block to respond to each scenario separately:
if (err) {
/* ... */
} else if (item) {
/* ... */
} else {
/* ... */
}

user Session in node.js

I have a form with username password fields that stores the username and passwords in node.js
How do I keep track of how many times an individual user is logged in. I want to output the number of sessions for a user beside each username in the list of logged in users
index.js:
var loggedInUsers = {};
var LoggedIn = 'TheUserIsLoggedIn';
function index(req, res) {
if (req.session.username) {
res.redirect("/users");
} else {
debugger;
res.render('index', { title: 'COMP 2406 Session Demo',
error: req.query.error });
}
}
function users(req, res) {
if (req.session.username) {
res.render("account.jade", {username:req.session.username,
title:"Account",
loggedInUsers: loggedInUsers});
} else {
res.redirect("/?error=Not Logged In");
}
};
function login(req, res) {
var username = req.body.username;
req.session.username = username;
loggedInUsers[username] = LoggedIn;
res.redirect("/users")
}
function logout(req, res) {
delete loggedInUsers[req.session.username];
req.session.destroy(function(err){
if(err){
console.log("Error: %s", err);
}
});
res.redirect("/");
}
exports.index = index;
exports.users = users;
exports.login = login;
exports.logout = logout;
Without any persistence layer, I would recommend:
if( loggedInUsers[username] ) {
loggedInUsers[username].timesLoggedIn++;
loggedInUsers[username].sessions.push( req.session );
}
else {
loggedInUsers[username] = {
timesLoggedIn : 0,
sessions : []
};
}
instead of:
loggedInUsers[username] = LoggedIn;

how to query a database using mongoose in node.js

I have written the following method that searches for a user in the database by their email.
/**
* Find a user by providing their email address
*/
DataProvider.prototype.findUserByEmail = function(callback, email) {
console.log("in findUserByEmail");
User.findOne({
emailAddress : email
}, function(error, user) {
if(error) {
console.log(error);
callback(error);
}
else {
console.log(user);
callback(user);
}
});
};
I'm trying to test it with the following:
function testFindUserByEmail() {
var expectedEmail = "user#user.com";
data.findUserByEmail(function(user) {
if (user.emailAddress === expectedEmail) {
console.log("User found");
} else {
console.log("User not found");
}
console.log(user);
}, "user#user.com");
console.log("test");
}
I get an outout of:
in findUserByEmail
test
It's like User.findOne() isn't getting called and I don't know why.
Other info:
var UserSchema = new Schema({
emailAddress : {
type : String
},
occupation : {
type : String
},
token : {
type : String
},
password : {
type : String
},
registrationDate : {
type : Date
},
activated : {
type : Boolean
}
});
/**
* Define Model
*/
var User = mongoose.model('User', UserSchema);
DataProvider = function() {
};
did you connected the database,
try: mongoose.connect('db-uri', function (err) {
next(err);
});

Resources