My simple code doesn't work with express-validator - node.js

I am studying about express-validator.
'router.post' passes without the validation
I made form and password input in html.
<body>
<h1>Hello Guys!</h1>
<p>Fill in your id number.</p>
<form action="/yournumber/sub" method="POST">
<input type="password" name="password">
<button type="submit">Summit</button>
</form>
</body>
And that password call router.post
This is my router code.
but this post runs redirect regardless of the length of password.
How could I make correctly?
router.post('/yournumber/sub', (req, res, next) => {
req.check('password').isLength({min: 4});
var errors = req.validationErrors();
if (errors) {
req.session.errors = errors;
req.session.success = false;
console.log('error');
} else {
req.session.success = true;
console.log('suc')
}
res.redirect('/ab');
});

I don't know the req.check()-notation and can't find it in the official documentation, but:
The way I use this module is as an express middleware. You can check the snipped on the linked documentation. Here is your adapted code:
const validation = [
check('password').isLength({min: 4})
];
router.post('/yournumber/sub', validation, (req, res, next) => {
var errors = validationResult(req);
if (errors.isEmpty()) {
// valid
} else {
// not valid
}
});
As you can see, the validation-array is passed in as another handler for the route. It works the same way as your handler:
Check if the parameter is valid, as specified to the check()-function
If not, add information to the req-object
Call next() to get to either the next validation or your handler.
Then, when you want to check the results, use validationResult() (which you spelled wrong and called as a method of req instead of passing it to the method).

Related

AngularJS, special character from Json via server

I'm trying to create a small multi-language project using NodeJS version 10.15.1, AngularJS version 1.5.8 and UTF8 encoded html. I should proceed with my own function instead of using other modules.
I created 2 different json files containing 2 different languages. The json is loaded via server using a $http call and the answer is stored inside a $scope variable.
$http.post(apihost + '/languages/language_frontend', {page: "home"}).then(function(language) {
$scope.language = language.json;
});
I pass the parameter page to filter with part of the json the function should retrieve.
router.post('/language_frontend', function(req, res, next) {
return new Promise(function(resolve,reject) {
if(config.language == 'it') return res.json({status: 'ok', json: italian_frontend[req.body.page]});
else if(config.language == 'en') return res.json({status: 'ok', json: english_frontend[req.body.page]});
});
});
This is (part) of one of the json
{
"home": {
"planning": "Pianificazione",
"activities_planning": "Pianificazione Attività"
},
"login": {
"test_one": "italiano uno",
"test_one": "italiano due"
}
}
And this is the html that displays the information
<div class="panel-heading">
<div class="row">
<div class="col-xs-3"><i class="fa fa-mobile-phone fa-5x"></i></div>
<div class="col-xs-9 text-right">
<div class="huge ng-binding">{{language.activities_planning}}</div>
</div>
</div>
</div>
The problem is that the displaying of activities_planning comes with an accented character and, coming from server side call, I don't know how to display it correctly. I'd like a general solution to implement everywhere, so I don't have to worry about few exceptions with special characters.
This is the result without a solution: Pianificazione Attivit�
Any suggestion?
So, here it is https://glitch.com/edit/#!/angularjs-specialchars. I tried to set up the same thing with you :
In my app.js on the backend, I get the content of JSON file and expose it in /language route :
const path = require("path");
const express = require("express");
const app = express();
const language = require("./test.json");
app.use('/', express.static(path.join(__dirname, 'public')));
app.get('/language', (req, res) => res.json({ status: "ok", json: language }));
app.listen(5000, function() {console.log("Server is running on port 5000")});
In my index.js on the client-side, I send a request to the server to get the JSON file :
angular.module("app", []).controller("MyController", ["$scope", "$http",
function ($scope, $http) {
// send request to get the json
$http.get('/language').then(function (resp) {
const language = resp.data.json;
console.log(language); // I've checked on the console.log, the text is OK
$scope.text = language.test; // bind to screen
});
}
]);
And in my index.html I just use it :
<body ng-app="app">
<div ng-controller="MyController">
<h1>Hello {{text}}!</h1>
</div>
</body>
What I have :

How to send data from react and use the request body in express, using Axios?

I use states to hold some form data in react, and what i want is, when i submit the form in react i send a post request using axios,and i want to use the form data in express. I tried req.body.params, req.body.data, req.body general,to access the request payload and they all returned undefined. Basically I want to access general(form data) in express. How can i do that?
note: the states are named general, and oneSuggestion, they are basic string states.
note:i searched similar questions for hours but none of them solved my question. if there was a solution, i couldn't find it, please excuse me.
edit: commented data, and put the states directly inside post.
React code:
function handleSubmit(e) {
e.preventDefault();
console.log(general, suggestionsForCases);
/*
let data = {
general: general,
oneSuggestion: oneSuggestion,
};
data = JSON.stringify(data);
console.log(data);
*/
let axiosConfig = {
headers: {
"Content-Type": "application/json;",
"Access-Control-Allow-Origin": "*",
},
};
axios
.post(
"http://localhost:8000/dict/",
{ general: general, oneSuggestion: oneSuggestion },
axiosConfig
)
.then((res) => console.log("success, dictionary sent,", res))
.catch((err) => {
console.log(err.response);
});
}
function handleInput(e) {
if (e.target.name == "general") {
setGeneral(e.target.value);
console.log(general);
}
if (e.target.name == "oneSuggestion") {
setOneSuggestion(e.target.value);
console.log(oneSuggestion);
}
}
return (
<div>
<form onSubmit={handleSubmit}>
<label>
general:
<textarea name="general" onChange={handleInput}></textarea>
</label>
<label>
suggestion:
<input name="oneSuggestion" onChange={handleInput}></input>
</label>
<button type="submit">submit</button>
</form>
</div>
);
}
export default AddDictionary;
express code:
const express = require("express");
const router = express.Router();
const Dictionary = require("../database/category/dictionary");
router.use(express.json());
router.get("/", (req, res) => {
console.log("success");
res.json({ msg: "success"});
});
router.post("/", (req, res) => {
console.log(req.body.general);
res.json({
msg: "success",
});
});
module.exports = router;
Ok, I found the problem. I deleted the axiosConfig from post, based on this source , and now this is the working code:
axios
.post(
"http://localhost:8000/dict/",
{ general: general, oneSuggestion: oneSuggestion }
)
.then((res) => console.log("success, dictionary sent,", res))
.catch((err) => {
console.log(err.response);
});
thank you guys for your help.
You'll need middleware in order to parse the request and make it accessible in req.body. I've assumed you're using a version after 4.16 which introduced express.json() as middleware for this scenario. I'll update my answer if you're using an earlier version.
Example using your code as a starter:
const express = require('express');
const app = express();
app.use(express.json());
app.post('/', (req, resp) => {
console.log(request.body.params);
});
app.listen(3000);
To explain, anything you post, aka let's say you posted the following object:
{
fruit: 'apple',
vegetable: 'onion'
}
After using the parser you'd access the posted data in req.body.fruit and req.body.vegetable.

flash messages are not saved before the page is rendered (node)

As part of a generic get route in an express application, I want to send two flash messages with express-session and connect-flash. This all works except that req.flash does not save before the page is rendered. As a result, the flash messages do not show until the user loads another page or the same page again.
The code for the last function in the route:
Post.countDocuments().exec(function(err, count){
if(err) {
console.log(err);
res.redirect("back");
}
req.flash("success", ["It's working", "Hallelujah!"]);
req.flash("error", ["Uh oh!", "We have a problem..."]);
res.render("index", {posts: allPosts, dates: dates, current: pageNumber, pages: Math.ceil(count / pageLimit), showing: showing, total: count});
});
and here's the code for one of the flash message templates (ejs):
<div class="flash flash-success">
<div class="flash-header">
<span class="flash-title flash-title-success"><i class="fas fa-check"></i> <%= success[0] %></span>
<span class="flash-close" onclick="return closeFlash(this);"><i class="fas fa-times"></i></span>
</div>
<hr class="flash-hr">
<div class="flash-body-success"><%= success[1] %></div>
</div>
I have tried using .exec() after req.flash to make the render statement run on completion but this didn't work and I've also tried req.session.save() with the render statement in a callback but this also failed.
The issue is not resolved by getting rid of one of the req.flash statements nor by only passing one string argument instead of an array of two.
The problem was that I had
app.use(function(req, res, next) {
res.locals.currentUser = req.user;
res.locals.error = req.flash("error);
res.locals.success = req.flash("success");
return next();
});
in app.js and so this middleware was run before the route had chance to set values for req.flash meaning that error and success were set to be empty.
I solved this by creating a function to save req.flash in res.locals just before rendering the page:
var toolsObj = {};
toolsObj.saveFlash = function(req, res) {
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
};
module.exports = toolsObj;

Delete a user with Mongoose, Express

I am new to Express and MongoDB. I created a small web app in Node.js and am using Express.js and Mongoose. I can succesfully create a user and have a user sign in but I am having trouble with a user being able to delete their account.
I have a user.js file in my routes folder which is where I am writing the code to signup, signin, delete, etc. Here is a link to the project on GitHub ( https://github.com/NicholasGati/shopping-cart-2 ). The button to delete a user's account is in views/user/edit.hbs. I put the button in a form. When I click the button, the user is not deleted and I am redirected to '/' for some reason. Note: '/:id' in my routes/user.js file becomes '/user/:id'.
Here is the code in the routes/user.js file for the delete method:
router.delete('/:id', isLoggedIn, (req, res, next) => {
User.findOneAndRemove({_id: req.params.id}, (err) => {
if (err) {
req.flash("error", err);
return res.redirect("/user/edit");
}
req.flash("success", "Your account has been deleted.");
req.logout();
return res.redirect("/shop/coffee");
});
});
Here is the form in views/user/edit.hbs:
<form action="/user/{{user.id}}" method="delete">
<div class="form-group">
<button type="submit" class="btn btn-danger">Delete Account</button>
</div>
</form>
Also, here is the isLoggedIn function:
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/");
}
Since you are new I think I should lead you to find the problem yourself:)
Make sure about form methods.
Make sure the route for user deletion is called.
If the markup doesn't seem right I am sorry cas I am using my phone to post this answer.
I had this exact same issue. I used an XMLHttpRequest from the client side in order to do this. I'm sorry I'm not experienced enough to explain why it worked this way and not from the node end, but it may have to do with form data being inherently designed to pass information, not delete information. In any case, try this solution.
In your client side code:
Your button code (form action shouldn't matter, and for that matter, the tag shouldn't either, since the logic is handled in the JS, but this is what I used):
<button id = "del-btn" class="btn btn-danger">Delete</button>
Script to send HTTP request from the button click, this code should go in the same file as your button above, or as an include JS file that the HTML page has imported:
<script>
var del_btn = document.getElementById("del-btn");
del_btn.addEventListener("click", function(e) {
var user = <%- JSON.stringify(user) %>;
var xhr = new XMLHttpRequest();
xhr.open("DELETE", "/user/" + user._id);
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText);
window.location.href = "/users";
}
};
xhr.send();
//make XMLHttpRequest to delete the poll here
}, false);
</script>
in your server side route, note how the response is just a success code. It's the XMLHTTP Request from the client side that does the redirection:
app.delete('/user/:id', isLoggedIn, function(req,res){
User.remove({
_id: req.params.id,
ownerID: req.user._id
}, function (err, user) {
if (err)
return console.error(err);
console.log('User successfully removed from polls collection!');
res.status(200).send();
});
});

Struggling to get callback to work express.js

Trying to make sure that request has completed before rendering page
Overview of app - submit for with code, make request, populate results page
//Index.js
var response = require('./requestMapping')
// home search page
exports.index = function(req, res){
res.render('index', { stationDisplay: response.station_id, test: 'rob' });
};
**//post from form to call METAR service
exports.post =('/', function(req, res, next) {
response.getMETAR(req.body.query,function(){
res.render('results', {
stationDisplay: response.station_id,
test: 'rob'
});
});
})**
//Index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= stationDisplay %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Enter ICAO code to get the latest METAR</h1>
<form method="post" action="/">
<input type="text" name="query">
<input type="submit">
</form>
</body>
</html>
Module to call webservice - requestMapping.js
/**
* #author robertbrock
*/
//Webservice XML
function getMETAR(ICAO){
var request = require('request');
request('http://weather.aero/dataserver_current/httpparam?datasource=metars&requestType=retrieve&format=xml&mostRecentForEachStation=constraint&hoursBeforeNow=24&stationString='+ICAO, function(error, response, body){
if (!error && response.statusCode == 200) {
var XmlDocument = require('xmldoc').XmlDocument;
var results = new XmlDocument(body);
console.log(body)
console.log(ICAO)
exports.station_id = results.valueWithPath("data.METAR.station_id");
//etc.
}
})
}
exports.getMETAR =getMETAR;
I can't see that your getMETAR function actually takes a callback function? I would expect it to be:
function getMETAR(ICAO, callback) {
// Do your work
var station_id = results.valueWithPath("data.METAR.station_id");
callback(null, station_id); // It's common to use the first arg of the callback if an error has occurred
}
Then the code calling this function could use it like this:
app.post('/', function(req, res) {
response.getMETAR(req.body.query, function(err, station_id) {
res.render('results', {stationDisplay: station_id, test: 'rob'};
});
});
It takes some time getting used to async programming and how the callbacks work, but once you've done it a few times, you'll get the hang of it.
Without seeing the rest of your code it hard to guess, but your code should look more like:
app.post('/', function(req, res, next) {
response.getMETAR(req.body.query,function(){
res.render('results', {
stationDisplay: response.station_id,
test: 'rob'
});
});
});

Resources