MEANJS mongoose model in request object - javascript

I've just started with meanjs. When I've taken a look at it server side module user profile controller, I find that mongoose model User is available in req object.
From where it has got added in req object?
Refer the code below, I wants to understand var user = req.user;, How user is added in req object?
'use strict';
/**
* Module dependencies.
*/
var _ = require('lodash'),
errorHandler = require('../errors.server.controller.js'),
mongoose = require('mongoose'),
passport = require('passport'),
User = mongoose.model('User');
/**
* Update user details
*/
exports.update = function(req, res) {
// Init Variables
var user = req.user;
var message = null;
// For security measurement we remove the roles from the req.body object
delete req.body.roles;
if (user) {
// Merge existing user
user = _.extend(user, req.body);
user.updated = Date.now();
user.displayName = user.firstName + ' ' + user.lastName;
user.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
req.login(user, function(err) {
if (err) {
res.status(400).send(err);
} else {
res.json(user);
}
});
}
});
} else {
res.status(400).send({
message: 'User is not signed in'
});
}
};
/**
* Send User
*/
exports.me = function(req, res) {
res.json(req.user || null);
};

In meanjs app.param([name], callback) is used, whenever a route with some id like articeId in parameter is accessed, app.param([name], callback) middleware is triggered. In meanjs it sets req.article like this.
app.param('articleId', articles.articleByID);
and in articleByID
exports.articleByID = function(req, res, next, id) {
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).send({
message: 'Article is invalid'
});
}
Article.findById(id).populate('user', 'displayName').exec(function(err, article) {
if (err) return next(err);
if (!article) {
return res.status(404).send({
message: errorHandler.getErrorMessage(err)
});
}
req.article = article;
next();
});
};
more on app.param see http://expressjs.com/api.html#app.param

Passport’s authentication middleware sets req.user upon successful login.
See http://passportjs.org/guide/authenticate/.

Related

Getting error: Error: Can't set headers after they are sent. after rerendering page

I am trying to build a registration page with nodeJS and firebase.
When the user gets a registration error the page reloads and the error is shown to the user.
Then if the user tries to register, he gets to the desired page but I get:
Error: Can't set headers after they are sent.
After several hours of researching, I think I have understood the problem.
My code is probably already in the Body or Finished state, but some function tried to set a header or statusCode
With this knowledge, I tried to solve this error but I don't get it done.
Here is my user.js(controller) code:
var express = require('express');
var firebase = require('firebase');
var router = express.Router();
var User = require('../models/user');
var errors;
var errorMessage;
/**
sign up
*/
//sign up page route
router.get('/', function (req, res, next) {
console.log(errors);
if (errors) {
//Handle the errors and show them to the user
res.render('signUp', {error: true, errorMessage: errorMessage});
}else {
res.render('signUp', {title: 'Sign up', user: false, login: true});
}
});
// sign up request
router.post('/', function(req, res, next){
console.log(req.body.user.email + ' made a registration request');
console.log('Passwword: ' + req.body.user.password);
var email = req.body.user.email;
var password = req.body.user.password;
//reference to the firebase database
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
if (error) {
console.log(error.code);
console.log(error.message);
errorMessage = error.message;
errors = true;
res.redirect('/');
}
});
//if user is logged in redirect to homepage
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
res.redirect('/users/home');
console.log('User: ' + user.email + ' has logged in');
}
});
});
module.exports = router;
I hope someone can help me.
If you are using version 7+ of node, you can use async/await like I did in the following snippet:
var express = require('express');
var firebase = require('firebase');
var router = express.Router();
var User = require('../models/user');
var errors;
var errorMessage;
async function createUser(email, password) {
return new Promise(resolve => {
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
if (error) {
console.log(error.code);
console.log(error.message);
errorMessage = error.message;
errors = true;
return resolve(true)
}
resolve(false)
});
})
}
async function authChange() {
return new Promise(resolve => {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log('User: ' + user.email + ' has logged in');
return resolve(true)
}
resolve(false)
});
})
}
// sign up request
router.post('/', async function(req, res, next) {
console.log(req.body.user.email + ' made a registration request');
console.log('Passwword: ' + req.body.user.password);
var email = req.body.user.email;
var password = req.body.user.password;
//reference to the firebase database
let error = await createUser(email, password)
if (error) {
res.redirect('/');
} else {
let logged = await authChange()
if (logged) {
res.redirect('/users/home');
}
}
});
module.exports = router;

Route.get() requires callback functions but got a [object Undefined] after modifying server routes

CODE:
server routes
'use strict';
/**
* Module dependencies
*/
var articlesPolicy = require('../policies/articles.server.policy'),
articles = require('../controllers/articles.server.controller');
module.exports = function (app) {
// Articles collection routes
app.route('/api/articles').all(articlesPolicy.isAllowed)
.get(articles.list)
.post(articles.create);
// Own articles collection routes
app.route('/api/articles/myarticles').all(articlesPolicy.isAllowed)
.get(articles.mylist)
.delete(articles.delete);
// Single article routes
app.route('/api/articles/:articleId').all(articlesPolicy.isAllowed)
.get(articles.read)
.put(articles.update)
.delete(articles.delete);
// Finish by binding the article middleware
app.param('articleId', articles.articleByID);
};
Controller
'use strict';
/**
* Module dependencies
*/
var path = require('path'),
mongoose = require('mongoose'),
Article = mongoose.model('Article'),
errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));
/**
* Create an article
*/
exports.create = function (req, res) {
var article = new Article(req.body);
article.user = req.user;
article.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(article);
}
});
};
/**
* Show the current article
*/
exports.read = function (req, res) {
// convert mongoose document to JSON
var article = req.article ? req.article.toJSON() : {};
// Add a custom field to the Article, for determining if the current User is the "owner".
// NOTE: This field is NOT persisted to the database, since it doesn't exist in the Article model.
article.isCurrentUserOwner = !!(req.user && article.user && article.user._id.toString() === req.user._id.toString());
res.json(article);
};
/**
* Update an article
*/
exports.update = function (req, res) {
var article = req.article;
article.title = req.body.title;
article.content = req.body.content;
article.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(article);
}
});
};
/**
* Delete an article
*/
exports.delete = function (req, res) {
var article = req.article;
article.remove(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(article);
}
});
};
/**
* List of Articles
*/
exports.list = function (req, res) {
Article.find().sort('-created').populate('user', 'displayName').exec(function (err, articles) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(articles);
}
});
};
/**
* List of own Articles
*/
exports.myList = function (req, res) {
Article.find({ user: req.user._id.toString() }).sort('-created').populate('user', 'displayName').exec(function (err, articles) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(articles);
}
});
};
/**
* Article middleware
*/
exports.articleByID = function (req, res, next, id) {
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).send({
message: 'Article is invalid'
});
}
Article.findById(id).populate('user', 'displayName').exec(function (err, article) {
if (err) {
return next(err);
} else if (!article) {
return res.status(404).send({
message: 'No article with that identifier has been found'
});
}
req.article = article;
next();
});
};
Server Policy
'use strict';
/**
* Module dependencies
*/
var acl = require('acl');
// Using the memory backend
acl = new acl(new acl.memoryBackend());
/**
* Invoke Articles Permissions
*/
exports.invokeRolesPolicies = function () {
acl.allow([{
roles: ['admin'],
allows: [{
resources: '/api/articles',
permissions: '*'
}, {
resources: '/api/articles/:articleId',
permissions: '*'
}, {
resources: '/api/articles/create',
permissions: '*'
}]
}, {
roles: ['user'],
allows: [{
resources: '/api/articles',
permissions: ['get']
}, {
resources: '/api/articles/:articleId',
permissions: ['get']
}, {
resources: '/api/articles/create',
permissions: '*'
}, {
resources: '/api/myarticles/',
permissions: '*'
}]
}, {
roles: ['guest'],
allows: [{
resources: '/api/articles',
permissions: ['get']
}, {
resources: '/api/articles/:articleId',
permissions: ['get']
}]
}]);
};
/**
* Check If Articles Policy Allows
*/
exports.isAllowed = function (req, res, next) {
var roles = (req.user) ? req.user.roles : ['guest'];
// If an article is being processed and the current user created it then allow any manipulation
if (req.article && req.user && req.article.user && req.article.user.id === req.user.id) {
return next();
}
// Check for user roles
acl.areAnyRolesAllowed(roles, req.route.path, req.method.toLowerCase(), function (err, isAllowed) {
if (err) {
// An authorization error occurred
return res.status(500).send('Unexpected authorization error');
} else {
if (isAllowed) {
// Access granted! Invoke next middleware
return next();
} else {
return res.status(403).json({
message: 'User is not authorized'
});
}
}
});
};
SITUATION:
I added app.route('/api/articles/myarticles') to my server routes.
Immediately, I get the following error in my terminal:
Route.get() requires callback functions but got a [object Undefined]
at Route.(anonymous function) [as get]
QUESTION:
What have I done wrong and how do I fix it ?
WHAT I LOOKED AT:
Express routes: .get() requires callback functions but got a [object Object]
I must have declared something wrong.
You have a simple typo error. You have articles.mylist instead of articles.myList:
app.route('/api/articles/myarticles').all(articlesPolicy.isAllowed)
.get(articles.myList) // <--- it should be myList instead of mylist
.delete(articles.delete);

Node JS MySQL Authentication

I am new to node JS. I am working on authenticating users against backend MYSQL.
Here is the code snippet of authentication
function Authenticate(username, password, fn) {
connection.connect();
var user;
connection.query('SELECT * from Users where username = ' +
connection.escape(username) + ' and password =' + connection.escape(password),
function(err, rows) {
user = rows[0].username;
});
if (!user) {
return fn(new Error('cannot find user'));
} else {
return fn(null, user);
}
connection.end();
}
This is my call back function.
app.post('/Login', function(req, res) {
Authenticate(req.body.username, req.body.password, function(err, user) {
if (user) {
req.session.regenerate(function() {
req.session.user = user;
req.session.success = 'Authenticated as ' + user;
res.redirect('Home');
});
} else {
req.session.error = 'Authentication failed, please check your username and password.';
res.redirect('Login');
}
});
})
I am getting an error, which i cannot get my head around.
TypeError: Cannot set property 'error' of undefined
at /...../.../node_modules/app.js:42:23
at Authenticate (/..../..../node_modules/app.js:82:11).
Please share your thoughts!
Takes the else out and see if any other req.session functions properly if not check if middleware is configured correctly for express validator

Everyauth is not working in express 4

I'm using nodejs, express 4 and everyauth for social network authentication. I'm having some problem where I click Accept from Google and and redirects back to my / I get
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
I'm using electrolyte as a DI as well but I don't think that would be an issue. Here's my code
index.js
var express = require('express'),
http = require('http'),
bootable = require('bootable');
var app = bootable(express());
app.phase(bootable.initializers('etc/init', app));
app.phase(bootable.routes(__dirname + '/routes.js', app));
app.phase(function listen(done) {
http.createServer(app).listen(process.env.PORT || 3000, function(err) {
if (err) { return done(err); }
var addr = this.address();
console.log('server listening on http://' + addr.address + ':' + addr.port);
done();
});
});
module.exports = app;
routes.js
var IoC = require('electrolyte');
module.exports = function routes() {
this.get('/', IoC.create('handlers/homepage'));
this.get('/api/foursquare', IoC.create('handlers/api/foursquare'));
//this.get('/auth/google/callback', IoC.create('handlers/auth/google_auth_callback'));
}
handlers/homepage
exports = module.exports = function() {
function render(req, res, next) {
res.render('index');
};
return [render];
};
google.js
var everyauth = require('everyauth'),
GoogleUser = require('../../app/models/google_user'),
mongoose = require('../../app/db/mongo');
require('dotenv').load();
module.exports = function() {
everyauth.google
.appId(process.env.GOOGLE_CLIENT_ID)
.appSecret(process.env.GOOGLE_CLIENT_SECRET)
.scope('https://www.googleapis.com/auth/plus.login') // What you want access to
.handleAuthCallbackError( function (req, res) {
// If a user denies your app, Google will redirect the user to
// /auth/facebook/callback?error=access_denied
// This configurable route handler defines how you want to respond to
// that.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokenExtra, googleUserMetadata) {
console.log('come back from google');
console.log(session);
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
/*
var googleUser = new GoogleUser(mongoose);
var johndoe = new googleUser({
accessToken: 'accessToken',
expires: new Date(),
refreshToken: 'refreshToken',
email: 'john#doe.com',
createdAt: new Date()
});
var promise = this.Promise();
promise.resolve(johndoe);
return promise;
*/
}).redirectPath('/');
};
mongo.js
var mongoose = require('mongoose')
require('dotenv').load();
var uristring = process.env.MONGOLAB_URI;
mongoose.connect(uristring, function (err, res) {
if (err) {
console.log ('ERROR connecting to: ' + uristring + '. ' + err);
} else {
console.log ('Succeeded connected to: ' + uristring);
}
});
exports = module.exports = mongoose
You will get Can't set headers after they are sent. if your code is like this
if (err) {
res.send(err);
}
else if(!user) {
res.send(info);
}
res.send(user);
In the above code, if user is undefined it sends the info as response and it again comes to next statement i.e res.send(user);. So it cannot set headers to the response which is already sent.
You can prevent this by
if (err) {
res.send(err);
}
else if(!user) {
res.send(info);
}
else {
res.send(user);
}
or
if (err) {
return res.send(err);
}
else if(!user) {
return res.send(info);
}
return res.send(user);

MEAN js require authorization to list items

In my mean js app i have an account model and corresponding routes and controllers. To remove a specific account i need to have authorization and I need to be logged in.
All users can however list all accounts, I only wont to list the accounts created by the specific user. So i need to add autorization to the list part of the code.
I update the routes for app.route('/accounts') with users.requiresLoginandaccounts.hasAuthorization as shown below:
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
var accounts = require('../../app/controllers/accounts.server.controller');
// Accounts Routes
app.route('/accounts')
.get(users.requiresLogin,accounts.hasAuthorization,accounts.list)
.post(users.requiresLogin, accounts.create);
app.route('/accounts/:accountId')
.get(users.requiresLogin, accounts.hasAuthorization,accounts.read)
.put(users.requiresLogin, accounts.hasAuthorization, accounts.update)
.delete(users.requiresLogin, accounts.hasAuthorization, accounts.delete);
// Finish by binding the Account middleware
app.param('accountId', accounts.accountByID);
};
Now I get an errror since req is not provided with user.
GET /modules/accounts/views/list-accounts.client.view.html 304 8.266
ms - - TypeError: Cannot read property 'user' of undefined
at exports.hasAuthorization (/Users/david/Repositories/budget/app/controllers/accounts.server.controller.js:103:17)
So I imagine i need to update the accounts.server.controller somehow. The delete account does provide an account in the req, so that only the creator can delete as I mentioned earlier. How do I update the code so that the "List of accounts" part work and list only the accounts belonging to that specific user?
/**
* Delete an Account
*/
exports.delete = function(req, res) {
var account = req.account ;
account.remove(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(account);
}
});
};
/**
* List of Accounts
*/
exports.list = function(req, res) {
Account.find().sort('-created').populate('user', 'displayName').exec(function(err, accounts) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(accounts);
}
});
};
/**
* Account middleware
*/
exports.accountByID = function(req, res, next, id) {
Account.findById(id).populate('user', 'displayName').exec(function(err, account) {
if (err) return next(err);
if (! account) return next(new Error('Failed to load Account ' + id));
req.account = account ;
next();
});
};
/**
* Account authorization middleware
*/
exports.hasAuthorization = function(req, res, next) {
if (req.account.user.id !== req.user.id) {
return res.status(403).send('User is not authorized');
}
next();
};
The account client service only contains the basic stuff:
//Accounts service used to communicate Accounts REST endpoints
angular.module('accounts').factory('Accounts', ['$resource',
function($resource) {
return $resource('accounts/:accountId', { accountId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
]);
And the user object is not mentioned in the controller.
The accounts.hasAuthorization assume it get executed after the accounts.accountById ,on your current configuration req.account will be undefined.
I'm assumming that somewhere in your account model you have:
user: {
type: Schema.ObjectId,
ref: 'User'
}
If you want the user only have access only to the accounts he/she owns :
Change accounts.list route only to requires Login and this gives us access to the req.user :
app.route('/accounts')
.get(users.requiresLogin,accounts.list)
Change the exports.list in the accounts controller:
exports.list = function(req, res) {
Account.find({user: req.user._id}).sort('-created')
.... //
};

Categories

Resources