How can I Post-redir-get without losing form data - javascript

Let's say a user gets a page /form/
GET /form/
He then fills in the form and sends a post request
POST /form/
The server attempts to validate user input and determines input to be invalid.
Currently the history chain for the users is
GET /form/
POST /form/
Now the server redirects the user to the GET /form/ page so it can fill in the form again (with error messages).
His history looks like
GET /form/ with filled in form fields
GET /form/ without filed in form fields
How do I send the user back without the user losing the details he entered in his first form?
What techniques are there for redirecting users back to their GET /form/ page and not forcing them to re-enter their information.
Below is my express (node.js) specific server side code for this example.
The validation middleware:
validate().on("error", function _error(msg) {
// store error message on request object
req.flash(msg, validateUserMessage[msg]);
}).on("valid", function _valid() {
// handle the rest of /POST/
next();
}).on("invalid", function _invalid() {
// redirect user back to last page, the /GET/ form
res.redirect("back");
}).run(function _validateUsers(check, sanitize) {
// validation logic.
});
The routing:
// GET /form/
app.get("/form", function _signUpView(req, res) {
// render /form/
res.render("auth/signup", req.flash());
});
// POST /form/
// validation middleware used here.
app.post("/form", secure.validateUser, function _signUpCreate(req, res) {
model.create(req.body, function _create() {
// create thing in database
});
});

DO NOT redirect on invalid input. Do it on valid input only.
On invalid input, respond to the POST request with the same form, but this time populated with the POST data that you just received.

I have decided to summarise the comments below into my answer:
To me, there seems to be only two sure ways of doing this:
1. Passing the user input parameters back from the server to the browser and repopulate the form either:
a) Using a parameters object passed to the view and populating each field using your severside language
b) Passing back a Json object and populating the form using loadJson
2. Using HTML5 local storage - which also requires JavaScript
If you do not persisit your data using either the server or JavaScript, then surely you are limiting yourself to relying on the browser - which is something you have no control over.
Good luck - if you do find a solution then please post it as your answer as I would be very intersted to see how you succeeded.

Related

How to only enable submit function, when smth in dropdown is slected

I am building a web app and have a question to my drop down menu.
The goal is, that the data can only be submitted, when a number is selected in the dropdown menu.
Just check if the dropdown is set or not should be enough. If the input of the request is invalid, the correct response would be a 400.
app.get('/lbc.js', (req, res) => {
if (req.body.dropdown === undefined || req.body.dropdown === null)
res.status(400).send({ message: "Drop down was not selected" });
return;
}
// continue with whatever you want if submit is possible
}
Your frontend needs to handle this response as well, because now it probably won't make a distinction when it works or not. So if you'd capture the submit event of the form, you could send the request yourself using the fetch api, and do different things for a 200 (when the response succeeded) or something like a 400 (request failed).
EDIT:
You can read up on how to create and handle submit events here:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event
Here you can read how you can send webrequests through javascript:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
These are the steps you need to do:
Put an id on your form, e.g. <form id="myForm" ... >
Start a JavaScript tag i.e. <script> </script>
Within these tags, first get the form reference:
const form = document.findElementById("myForm");
Put a submit event listener on it like how they do in the link
In the event handler function, send the request, and deal with the response (show message if error, do something else if success for instance).
EDIT april 7th:
About your code and your comments I have the following to say:
You have created 2 forms, one for your dropdown and one for your button. Both of them should be in the same <form></form> tag. When you click your submit button, all <input> fields will be sent to whereever your form submits to.
You seem to need to check if all fields are filled in correctly before you send the data to your server. Like I said in my previous answer, you need to create a script that will do this. In this link you can read again in a simple way how to do such a thing
Checking if a field has a value is again done by obtaining the element through it's id. E.g. if you have an input like: <input type="text" id="firstName" name="firstName" />, you can obtain the value of this field in javascript as such: const valueFromField = document.getElementById("firstName").value;
Hopefully this will give you some hints to make some new steps.
In my humble opinion it would probably be a good idea for you to do some basic javascript tutorials to give you some insight on how that stuff works.
According to the given details, Try this.
You can check the value and perform your actions as below.
if(req.body && req.body.dropdown) {
res.send('submit is possible')
} else {
res.send('Please select the amount!')
}
Also use, POST method route
app.post('/test', function (req, res) {
res.send('POST request to the homepage')
})
Read more about Express.js routing

Set HTML Input invalid on server

I'm using HTML5 form validation to validate my form. So if I validate it using Javascript, I can do something like that:
if (isInvalid())
{
myControl.setCustomValidity("my error message");
}
And it's working fine. My doubt is about server-side validation. The form is posted back to the same page, and if an error is detected, the input control should be considered invalid from the start, something like that:
<input type="text" name="id" invalid error-message="This id is already used" />
I don't want to use AJAX to make this validation, because I would have to 'hijack' and cancel the form submit, make the validation using AJAX, and then submit the form in javascript.
It is always better to iterate over context
You are not using AJAX and are sending form over http page load
One thing to keep in mind is either ways AJAX or otherwise form will only follow course on clicking of submit button. Hence the name form submission.
With in the form we have a field which may be valid or invalid.
If the field is invalid then run error which seems to work or if field is valid then simply glide through to next step in form submission.
On server side detect if field is invalid or not .... and do what ever is dependant on the context.
Issue on server side is it has nothing to do, nor controls and nor wants to control UI, html display in your browser.
All it handles is request i.e. GET, POST, PUT, HEAD etc and responds accordingly.
Browser sends page request to web server - it may pack form data or it may not pack form data dependant on the context.
Web server fetches the page and forwards if there is any packed form data with the request to the page and there is always lot more data getting passed around other then just form e.g. cookies, User agents, IPs etc
once the page is loaded into process stream you little bit of programming tells it to find form data if there is any and processes that for data to make a response out put.
So we are having a conflict of interest between point no 4 and point no 5.
Thing is your form is ultimately just a payload for HTTP (which is just a payload for tcp in turn and so on).
HTTP inherently does not and should not identify data types in payload, it is just an array for HTTP. KEYWORD FOCUS array.
You can select how to represent data in the array
It may look something like this
GET /?say=Hi&to=Mom HTTP/2.0
Host: foo.com
read more here how forms are sent to webserver
So bottom line forms are only going in some form of array format, we know arrays always have key value pair e.g. ['say' => 'hi'] there is key and there is value.
usually java-script does not offer out of the box key value pairing for arrays it has values and uses their index as key e.g. ['hi', 'there'] behind the scene is equivalent to in some hackyway to [0 => 'hi', 1 => 'there'] just keep that in mind java script does not offer multidimensional arrays out of the box.
so how does java script handle arrays or how we define it we it goes like this
var say = ['hi'];
now you may see whats happening around say=Hi in form data. There is massive array of Get with in which are key value pairs separated by &
for php sake it looks something like this
$_GET = [
'say' => 'hi',
'to' => 'mom']
we detect in page through $_GET['say'] which returns the value against it.
This is universal and will remain this for a long time to come.
What you are trying to do it attempting to detect on server from form data wither any of the key value pair has valid value or not.
Well reason why url sending is so fast it happens in less then 2 seconds gone from one part of the planet to another. While response as in downloading the web-page is so slow because inherently do not send html code through url request as show in example above. they send militaristic information understood universally.
This in turn means since there is html going to server then sever cannot detect any attributes they only have key value pair. So out attribute detection is out of window. Through error and trials we developers get the hang of this explicit revelation.
Anyways so how do we deal with this;
Some make cookies some make extra hidden fields
Then trigger on submit event on form to do the magic they need to do
some even run server side validation by running validation function on server e.g.
if($_GET['say' != 'hi'){do this thing something} else { do that thing}
Trust me there are always some kind of function or loop run on server side to make validation. WE have not found default validation way as of yet.
So we use form on submit event
document.getElementById('myform').onsubmit = function() {
var cheking = document.getElementById('myfield').value;
if(cheking != 'what ever you want'){
alert('fail!');
return false; // prevent the form to submit
}
}
This is the general idea dont submit form which is half crooked but incase it does need be sent then slight change of code
document.getElementById('myform').onsubmit = function() {
var cheking = document.getElementById('myfield');
if(cheking.value != 'what ever you want'){
cheking.value = 'invalid';
alert('fail!');
}
}
form will submit and on server side for that key we will have value as invalid so php side would be
if($_GET['myfield' = 'invalid'){stop processing or whatever else } else { keep on processing}
Because this had been going on for so and so and so long it became a standard of its own through input pattern attribute which takes care of all of the above on client side and is pretty much what you have done.
input pattren
bunch of regex to help you along
<!DOCTYPE html>
<html>
<body>
<h1>The input pattern attribute</h1>
<form action="">
<label for="country_code">Country code:</label>
<input type="text" id="country_code" name="country_code" pattern="[A-Za-z]{3}" required oninvalid="runvalidity(this)" oninput="this.setCustomValidity('')"
title="Three letter country code"><br><br>
<input type="submit">
</form>
<script>
function runvalidity(ele){
ele.setCustomValidity('Enter country name please');
ele.value = "invalid";
}
</script>
</body>
</html>
we created a pattern which on on submit event will manage and wont send form the in JavaScript we have run bunch of events on input field where we call custom function which makes UI as you wanted and alters the input value. if for any reason form does go through with invalid value we can then run server side validation as shown above using the same logic.
nevertheless browser will only send count_name=invalid or country_name=usa etc
Hope gist helps you understand whats behind the scene. my suggestion will be develop a UI context then fit in code logic (key word logic) matching both on client and server side.
I personally use pasterns and filet through same conditions on server side. some time client side logic can be tightened up so much there is lesser need to compare on server side. Again it depends how one fits in their code logic.

Form input to http post request

I have an Angular Bootstrap project- a form with some fields like name, email, phone, etc. to fill in. The form is written in HTML, in a file called customer-form.component.html. Upon submission, a JSON object is created with the values of the fields and displayed on-screen.
I am writing a HTTP POST request in the file customer-form.component.ts. The method in question looks like this:
postProfile() {
this.httpClient.post('API server url',
{
name:this.name,
phone:this.phone,
email:this.email,
yesorno:this.yesorno
})
.subscribe(
(data:any) => {
console.log(data)
}
)}
I set it up so submission of the form would also submit the POST request to the server. I am using Chrome to debug, and in the console I get the error message:
"Failed to INSERT or UPDATE Customer record due to: [com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'NAME' cannot be null]"
I changed the code to name:name once, and a submission got through. But when I checked it in the server, it had a blank name (name:''), and some true/false fields and fill-in numerical fields. Email and phone were not even represented, blank or otherwise, in the submission. Now if I try to submit something with name:name, it is counted as a duplicate and does not work. No matter what I fill in the form before I submit, the complaint is that the name field is blank.
My main question: Is there a way, preferably by referring to the JSON object, to accurately populate the POST request fields based on input fields? The JSON object is defined/created in a script in the index.html file.
My second question: What on earth is being used to populate the POST request right now? Even if I fill in the fields, the name field is blank upon submission. I have a model Customer object in customer-form.component.ts (like below), and I suspect that is how the original submission was populated (except the name?).
model = new Customer('Harry', 11111111111111, 'pott#r', true);
Please let me know if more information is needed.

Best way to prevent parameter tampering and send values with Javascript?

I am posting a form to the controller and making it asynchronous. I am storing values in input form hidden. When a button is clicked, a javascript function is called. It both fetches the value from an input field, as well as a value from input form hidden. It then sends a json string to the controller to handle this request.
Controller:
[HttpPost, Authorize]
public ActionResult DoSomeStuff (string leagueName, string doSomething) {
var service = new Service(_db);
var league = service.GetLeague(leagueName);
if (league != null) {
// validate doSomething
league.Action = doSomething;
_db.SaveChanges();
}
return new EmptyResult();
}
Javascript:
$(document).on("click", "#submitForm", function () {
var json = {
"leagueName": $("input[name=leagueName]").val(),
"doSomething": $("input[name=doSomething]").val()
};
$.post("/Home/DoSomeStuff/", json, function () {
// async display something
});
}
Html:
<input type="text" name="doSomething">
<button type="submit" id="submitForm"</button>
<input type="hidden" name="leagueName" value="#item.League.LeagueName" />
What is the best way to let javascript fetch a stored value (more secure way then input type hidden)?
How can I prevent some user from altering the value from the input type
hidden field?
How can I prevent some user from altering the value from the input
type hidden field?
You cannot!
What is the best way to let javascript fetch a stored value (more
secure way then input type hidden)?
The general rule is, do not trust data coming from client. You should always validate it on server before doing anything.
If you are worried about a user update the league name field value in the form to some other users league name and post it, What you should be doing is, explicitly checking whether the user has proper permission to do something on the posted league in your server code.
[HttpPost, Authorize]
public ActionResult DoSomeStuff (string leagueName, string doSomething) {
var service = new Service(_db);
var league = service.GetLeague(leagueName);
// Now check whether the current user has access/permission
// to perform some operation on this league.
// Ex : if(!service.IsUserAuthorizedToDoSomething(league))
// {
// return View("NotAuthorized");
// }
//to do: Return something
}
If the value needs to come from the client (and be part of the HTTP request) then there's absolutely nothing you could do to prevent the client from modifying its contents. If the client is not supposed to modify the contents of some fields then those fields have nothing to do in your markup and be part of the postback HTTP requests (be it as hidden fields or whatever markup element comes to your mind). They should safely reside on your server (database?) and be retrieved using some identifier coming from the client. Obviously whether the client can access the information related to this identifier is subject to something called authorization. Basically you should first know who your client is (authentication) and then verify in your data model if this client has access to the corresponding records. It's as simple as that.
[HttpPost]
[Authorize]
public ActionResult DoSomeStuff (string id, string doSomething)
{
var service = new Service(_db);
var league = service.GetLeagueById(id);
if (!HasAccessToLeague(User.Identity.Name, league))
{
// you are not suppose to modify the contents of this league
// throw him a 404 or something
}
else
{
if (league != null)
{
// validate doSomething
league.Action = doSomething;
_db.SaveChanges();
}
}
return new EmptyResult();
}
obviously the implementation of the HasAccessToLeague(string username, string leagueId) method will greatly depend on your data model and how your authorization logic.
Also you used XSS in your question title but here your problem is not about XSS or javascript but rather designing authorization layer in your web application.
of course its possible to do this! After all, your server app manages to track who the currently logged on user is using insecure client storage.
When a user logs on, the server will generate a secret message and store it in an encrypted token that's passed to the client and bak in a cookie (which is just another piece of unsecured client data storage). When you send requests to the server, it gets the cookie, decrypts it, and checks the data inside to tell who the user is.
You can do the same - for the hidden fields, encrypt them, put them in a hidden input (or a cookie if you prefer) and send them back to the server. However, you can only use them in your client javascript if you send them plain text as well, which means you need to still perform some checking on the server, but that checking can be as simple as comparing the encrypted values with the hidden form values, if any do not match, reject the request.
things to bear in mind though, encrypion is slow. It can be quicker to fetch the values from a DB instead, though you might use a cache for these. YMMV.
An alternative option is to generate a javascript file with the values in and ensure that the client browser cannot edit them using security features such as content-security-policy. The disadvantage is an inability to use these values in html (as obviously the user can edit them there) so you'll have to pass data back to the server via js calls.

auto-saving the contents of a WTForm

I am making a (quite frankly) somewhat tenuous form. As such, I want it to save every time they input something into a data field. However, I don't want to save them as a user to the site until the form is complete and validated.
This is what I imagine the javascript side to contain
$('input').blur(function() {
$.post(endpoint, form);
});
however, what I currently have for the endpoint is something like this:
#auth.route('/register', methods=['GET', 'POST'])
def register():
""" register a new user using the form """
form = RegistrationForm()
if form.validate_on_submit():
new_user = User(
email=form.email.data.lower(),
first_name=form.first_name.data.title(),
last_name=form.last_name.data.title(),
username=form.username.data.lower(),
password=form.password.data
)
db.session.add(new_user)
flash('successfully registered!', 'success')
return redirect(url_for('auth.login'))
return render_template('user/register.html', form=form)
this works well to register a user, but how do I simply save their form data for later use if they revisit without making them a user?
I think you have to store each session into database, you have to load the partial filled form data when the session and cookie communicates.
IMHO, when the new user comes to the application new session will be created, you have to store that session into database, if the user starts filling the form you have to update the data along with session variable, then when the same user tries to access next time, the same session need to be loaded from the database. The session has to be identified from the cookie input like
identify the session using sid
sid = request.cookies.get(app.session_cookie_name)
followed by, you have to load the partial filled form data along with that particular session.
loading the session back
response.set_cookie(app.session_cookie_name, session.sid,
expires=self.get_expiration_time(app, session),
httponly=True, domain=domain)
The example code is already done by some GOD for you :)
I assume you are already aware of storing and retrieving the form data.

Categories

Resources