auto-saving the contents of a WTForm - javascript

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.

Related

Rails - Send alert to another user when they are assigned a new client (without refreshing their page)

I have a User model using devise and a Trader model. I want to send a popup message or alert to users whenever they are assigned a new Trader.
Managers can assign traders to users so the assign process is done by a different user than the user receiving a new trader.
How to I make the manager's 'assign' action send an alert to the specific user who has been assigned a new trader? They will be logged in but I don't want them to have to refresh their page
Assign method in traders_controller.rb
if #trader.save
// Send alert to user if #trader.user == current_user
flash[:notice] = "Successfully created trader." // flash message for manager
redirect_to traders_path
return
else
render :new
return
end
You need to use a socket to push the new information to the appropriate client. If you're using Rails 5, you can use ActionCable. You'll want to subscribe the user to a channel specific to them, then publish information on that channel to update the user. Of course, your front-end will need to know what to do with the data.
https://guides.rubyonrails.org/action_cable_overview.html#client-server-interactions-subscriptions
If you're on an older version of Rails, take a look at this article:
https://medium.freecodecamp.org/implementing-web-sockets-in-a-rails-4-fb45696f8d8c.

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.

save passwords for my website using JavaScript

Rigth now i'm creating my own website and there need to be a log in function. I've made a sign up page that retrieves data from the input fields and now comes the problem. I don't know how to save the passwords and username etc. Is it possible to save this into a text file and every time i open the website it retrieves this data? So, yes how do i do this and if this can't is there another way?
Here you see the code it retrieves. These variables need to be safed in a text file and retrieved next time website will be opend
var voornaam = document.getElementById("voorn").value;
var achternaam = document.getElementById("achtern").value;
var mail = document.getElementById("mail").value;
var password = document.getElementById("pass").value;
var gender = document.getElementById("iGender").value;
Solution:
Use a Database to save this information. Here a some Databases Mongo DB and Firebase
https://www.firebase.com/
Here's a course for Firebase http://www.codecademy.com/en/tracks/firebase
In addition to hashing the password, you probably want to be storing this information in a database. You will then have to add some logic to your application so that when a user logs in to your website, the values they enter into the log in form are checked against the values stored in the database when they signed up. In very general terms, that is probably the most standard architecture to get a log in functionality up and running.
You will have to write a service on your server that takes the form values, checks them against a database and then updates the HTML accordingly.
You could create a cookie and read it when the page loads: http://www.w3schools.com/js/js_cookies.asp
Create: document.cookie = "voornaam="+voornaam
Read: $(function(){ voornaam = document.cookie.replace("voornaam=",""); })
EDIT:
To save objects, you can use the JSON-library like so:
document.cookie = JSON.stringify({foo:"bar"}); cookieObject = JSON.parse(document.cookie);
But have in mind that the user can read and manipulate this cookie...

Hidden arguments from Javascript to Django view

I am currently working on integrating Facebook Login into my website.
In javascript, I was able to fetch the user's information the moment (s)he logs to my website; via Facebook.
So, part of my javascript code is the following:
...
u_email = response.email; //gets user's email
u_fname = response.first_name; //gets user's first name
...and so on!
Now I would like to do one of the two following scenarios: 1) If this is the first time the user logs in into my website; I would like to save all this information (email, first name, ...) to my users' database; 2) If this is not the first time the user logs in, I would like to redirect the user to another page, and display some information about him/her that I will need to get from the database (according to his/her email)!
In either case, I will have to access the database through the user's information. So, what I would like to do, is to redirect the user to a Django view while passing the user's information. For example, I can have the following in my javascript file:
document.location.href = '../' + u_email +'/' + u_fname + '/login';
...and in my urls.py, I can have the following:
url(r'^(?P<u_email>\w+)/(?P<u_fname>\w+)/login/$', views.login, name='login')
Lastly, in my view file, I can have the following:
def login(request, u_email, u_fname):
template = loader.get_template('counters/login.html')
context = RequestContext(request, {
'u_email': u_email,
'u_fname': u_fname,
})
return HttpResponse(template.render(context))
Now; clearly, I have a problem, that is, the user's (supposedly secretive) information will be shown in the url! Is there a way to avoid it by hiding the arguments passed from the javascript to the Django view?
I think you should not have url patterns based on critical information a potential attacker should not be able to see. This type of information should be passed to the server side using a POST request method in an encrypted ssl or tls request.
But for your usecase a better approach to achieve that is to :
use the FB javascript api to login on client side and get a FB token
send a POST https request to your backend and have your backend code requesting the user information using the FB Graph Api. (the ssl and tls request is necessary to pass the access_token information in POST mode, this is here the sensitive data)
#the view code
#import your user model here
import requests
from django.shortcuts import render_to_response
#POST_required
def login(request, facebookId):
if token is not None:
#query graph api
r = requests.get('https://graph.facebook.com/{facebook_id}?fields=email,name&access_token={token}'.format({'facebook_id':facebook_id, 'token':token}))
facebook_email = r.json()['email']
facebook_name = r.json()['name']
#check if first login
try:
user = Users.object.get(email=facebook_email, name=facebook_name)
except Users.DoesNotExist:
user = Users.objects.create(email=facebook_email, name=facebook_name)
render_to_response('counter/login.html', dictionnary={'user':user}, context=RenderContext(request))
#url conf code
from django.conf.urls import patterns, url
import views
url_patterns = url('',
patterns(r'^(?Pw+)/login/$', views.login)
According you have an Model to save the User information and his email is unique.
def login(request, u_email, u_fname):
try:
# Try to get the User in your DB
user = YourUserModel.objects.get(email=u_email)
# Do your redirects.
except YourUserModel.DoesNotExist:
# Do your other stuffs, like add this new user in your DB
template = loader.get_template('counters/login.html')
context = RequestContext(request, {
'u_email': u_email,
'u_fname': u_fname,
})
return HttpResponse(template.render(context))

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

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.

Categories

Resources