In node 8.11.1, express 4.16.3 I installed
"express-messages" : "*",
"connect-flash" : "*",
"express-validator" : "*",
"express-session" : "*"
I have a page that gets all articles app.get('/', function(req, res){.... and also has a "New" button, for adding a new article. When hitting New, a pop-up Bootstrap form appears.
I want to check for empty form fields. The HTML form field that I check is
<input type="text" name="name" id="name" class="form-control" />
The form's action goes to
const { check, validationResult } = require('express-validator/check');
app.post('/add', [check('name').exists()],
function(req, res) {
const errors = validationResult(req);
console.log(errors.isEmpty());
if (!errors.isEmpty()) {
req.flash('err', 'errors'); //test
res.redirect('/');
}
else {
pool.connect(function(err, client, done) {
if (err) {
return console.log('db connect error '+ err);
}
client.query('insert into event (name) values($1)',
[req.body.name]);
done();
req.flash('success', 'saved');
res.redirect('/');
}); //pool connect
}//else
});
I am based in this. Whatever I do, the console.log(errors.isEmpty()); is always TRUE, so I end up saving to my DB empty fields. So, the express-validator does not catches errors ?
Also, I am not sure how to pass the errors back in the / route, so the errors can be rendered, this is why I just use req.flash('err', 'errors'); for now. Do I use req.flash like for the success part?
Please help me debug this.Thanks
express-validator maintainer here.
Regarding express-validator letting empty strings come through
check() will create a validator chain for something in the request named name.
It's not assertive of the location of the field, it could be req.query.name or req.body.name, for example.
If you want specifically req.body, then use the other chain creator body().
Then, even if you do have name in req.body, please note that check('name').exists() is not validating its content. It's simply checking it exists, as the name says.
If you want to check that it has some content, whatever that is, you can use check('name').not().isEmpty().
Regarding passing the errors to the redirected page
You can call either errors.array() or errors.mapped() to get the actual errors (please check the Validation Chain API for details).
I haven't used req.flash, so you should test if you can pass an JS object in there, or if you can only pass strings.
If you must use a string, then JSON.stringify/JSON.parse should be your friends to transport your errors.
Related
I am working on nodejs express with mongoose. Every user has such as exvariable which controls permission to have exvariabletext.
My user model schema exvariable and exvariabletext;
exvariable : {type:Boolean,default:false},
exvariabletext:{type:String,default:null}
When I am trying to find user and check if(user.exvariable === false), I am getting an Error such like that TypeError: Cannot read property 'exvariable' of null. So I can't use the default value and update it.
I have tried to change the default value in schema and control in nodejs syntax but couldn't pass the error and I want to understand the logic.
And my code like this;
router.post("/setexvariable",(req,res)=>{
User.findById(req.params.id,(err,user)=>{
if(err){
console.log(err);
req.flash("error","Oops, try again 😔");
res.redirect("back");
}
if(user.exvariable == false){
user.exvariable=true;
user.exvariabletext=req.body.text;
user.save();
req.flash("success","Welcome 😍");
res.redirect("/somewhere",{user:user});
}else{
req.flash("error","You already has a exvariable 😔");
res.redirect("back");
}
});
});
You have to set the id parameter in your route to be able to access it with req.params.id. In your code, req.params.id is undefined, so your query returns null.
You should have something like router.post("/setexvariable/:id", (req, res) => {...}). More on route params in Express's documentation.
I have the following view
router.post('/save',
[
body('name').not().isEmpty().withMessage('name empty'),
body('surname').not().isEmpty().withMessage('surname empty'),
body('email').not().isEmpty().withMessage('email empty'),
body('password').not().isEmpty().withMessage('password empty')
],
(req, res)=>{
let errors = validationResult(req);
if (!errors.isEmpty()) {
req.session.msgs = errors.array({ onlyFirstError: true });
return res.redirect('/signup');
}
//save form data......
});
Ok, so I get some data from a login form and I want to go back to that login form , with some error messages.
It all works fine except that the form is empty after the redirection. If I put everything except, say password, I go back to the form and is empty , so I have to fill it again from scratch along. I want to go back and the name, surname and email be still there and re-enter just the password.
Is there a way to go back and whatever fields where not empty, still have their values?
Thanks
[node 8.11.1 + express 4.16.3 + express-validator]
As you are using node 8.x you can use one for core modules of nodejs which is
querystring. And using this, you can send the data in query string. The idea is to send the received parameters back to redirected view like
const params= querystring.stringify({
"name": body('name'),
"surname": body('surname'),
"email": body('email')
...
});
res.redirect('/signup?' + params);
Now these parameters will be available on your view and you can access them in singup view and fill the related fields
I'm working on a simple login for a web application, and can't seem handle .getValidationResult() correctly. I've spent quite a bit of time pouring over the npm documentation for express-validator, trying to find an answer in tutorials, and looking on sites like Stack Overflow without managing to find the answer to my question. Perhaps I just don't know the right question to ask.
I want to ensure that
the user submitted something that has the form of an email address,
that the password isn't empty. I then want to
sanitize the email before interacting with the DB later on, then
check to see if any of the first 3 procedures failed. If there were failures, return the user to the login page.
My question is what is the correct way to use express-validator's .getValidationResult()?
Here's the offending piece of code:
export let postLogin = (req: Request, res: Response, next: NextFunction) => {
req.assert("email", "Email is not valid").isEmail();
req.assert("password", "Password cannot be blank").notEmpty();
req.sanitize("email").normalizeEmail({ gmail_remove_dots: false });
req.getValidationResult().then(function(result){
if (result != undefined) {
console.log(result.array();
return res.redirect("/login");
}
});
//do other login related stuff
}
I'm guessing that something simple is causing my error here, but I can't seem to find what it is.
It returns a promise for an object called Validation Object. This object contains information about the errors that your application has had.
The explanation.
Runs all validations and returns a validation result object for the
errors gathered, for both sync and async validators.
All it does is returning errors if there is one. Here is some example code returned by that function.
//The error object
{
"msg": "The error message",
"param": "param.name.with.index[0]",
"value": "param value",
// Location of the param that generated this error.
// It's either body, query, params, cookies or headers.
"location": "body",
// nestedErrors only exist when using the oneOf function
"nestedErrors": [{ ... }]
}
The function returns isEmpty() when there is no errors to display.
The function returns .array([options]) if there are any errors. Errors are located in [options] array.
Check out this link for the example code of what it might return.
UPDATE
You can also just use it like this, which is easier.
Please note that this is new API as of v4.0.0 release of express-validator.
const { check, validationResult } = require('express-validator/check');
//go to a link
app.get('/myURL', (req, res, next) => {
// Get the validation result\
const errors = validationResult(req).throw();
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors }); //err.mapped()
});
I have a function that gets the id of the user when she registers
user.save(function(err, id){
if(err) return next(err);
req.session.uid=id;
})
Then, I wrote this middleware
var User = require('../user');//contains the code above
module.exports = function(req,res,next){
var uid = req.session.uid;
if(!uid) return next();//if not logged in
else{//else is logged in
User.get(uid, function(err, user){
//get user object and pass it to locals
if (err) console.log("error from midd > "+err);
req.user = res.locals.user = user;
next();
})
}
}
I define my middleware in the app.js like so
var user = require('./lib/middleware/user');
app.use(session({resave:'false', saveUninitialized:'false', secret:'secret'}));
app.use(user); //<-- my middleware
app.use(express.static(path.join(__dirname, 'public')));
app.set('multimedia', __dirname + '/public/multimedia');
app.use(messages);
app.get('/register', register.form);
app.post('/register', register.submitit);
Then I check if there is an id in the locals and show the right menu, by using ejs
<%if (locals.user) {%>
<div id='menu'>
<a href='/post'>post</a>
<a href='/logout'>logout</a>
</div>
<%}else{ %>
<div id='menu'>
<a href='/login'>login</a>
<a href='/register'>sign up</a>
</div>
<%}%>
This never works. In every page, even if I am registered, I never see the menu for the registered users (post and logout).
I put many console.log all over the code and looks like the middleware never gets the session.uid.
console.log("req.session.uid = "+req.session.uid); inside the middleware always gives undefined, even though saving the user works and returns an id that I pass to session req.session.uid=id;
How do I fix this? Please advise because I am stuck.
Thanks
Note: I cannot be sure this is your error because you didn't paste the code around user.save(). But I'm enoughly confident that is the cause.
Session.Save(): This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.
As I can see here:
user.save(function(err, id){
if(err) return next(err);
req.session.uid=id;
})
You either:
Fail to save the new user and continue the process with next(err) (which end the HTTP response)
Or succeed and probably get stuck (<= not enough code shown to know what...)
In case of success you should probably call next() or next(null).
Because of that, the altered session (ie: req.session.uid=id;) is never saved. Thus, resulting in a failure of retrieving the uid in the middleware.
I got very confused for one usage:
In the route file:
app.param('userId', users.load);
And the users.load function:
exports.load = function (req, res, next, id) {
var options = {
criteria: { _id : id }
};
User.load(options, function (err, user) {
if (err) return next(err);
if (!user) return next(new Error('Failed to load User ' + id));
req.profile = user;
next();
});
};
Here, route should have the userId to response but why does the author use req.profile here. profile is not a property.
Anyone can help?
Thanks.
What the code does is this: for routes that have a userId parameter (that is, routes that look similar to this: /user/:userId), Express will call the load() function before the route handler is called.
The load function loads the user profile belonging to the userId from the database, and adds it to req as a newly created property req.profile.
The .profile property name is arbitrarily named by the author and demonstrates the fact that it's perfectly valid to add properties to req (or res, for that matter, but convention is to add these properties to req).
In the route handler, you can then use req.profile. It's basically a way of propagating data from middleware and app.param() implementations to other parts of the route handling.
the line req.profile = users; think of it this way, 'i want to take all the powers of the users and paste them to req.profile' why? remember this part is sort of a middleware if you want to target any of the read, update and delete code it has to pass through here, it only makes sense if it involves the req, because you are practically requesting to access the said pages (read, edit and delete or any other:userId page) now the profile name doesn't matter you could use any name but its sort of a convention in the community to use the profile name.