Server side form validation and POST data - python

I have a user input form here:
http://www.7bks.com/create (Google login required)
When you first create a list you are asked to create a public username. Unfortuantely currently there is no constraint to make this unique. I'm working on the code to enforce unique usernames at the moment and would like to know the best way to do it.
Tech details: appengine, python, webapp framework
What I'm planning is something like this:
first the /create form posts the data to /inputlist/ (this is the same as currently happens)
/inputlist/ queries the datastore for the given username. If it already exists then redirect back to /create
display the /create page with all the info previously but with an additional error message of "this username is already taken"
My question is:
Is this the best way of handling server side validation?
What's the best way of storing the list details while I verify and modify the username?
As I see it I have 3 options to store the list details but I'm not sure which is "best":
Store the list details in the session cookie (I am using GAEsessions for cookies)
Define a separate POST class for /create and post the list data back from /inputlist/ to the /create page (currently /create only has a GET class)
Store the list in the datastore, even though the username is non-unique.
Thank you very much for your help :)
I'm pretty new to python and coding in general so if I've missed something obvious my apologies.
Tom
PS - I'm sure I can eventually figure it out but I can't find any documentation on POSTing data using the webapp appengine framework which I'd need in order to do solution 2 above :s maybe you could point me in the right direction for that too? Thanks!
PPS - It's a little out of date now but you can see roughly how the /create and /inputlist/ code works at the moment here: 7bks.com Gist

I would use Ajax to do an initial validation. For example as soon as the user name input box loses focus I would in the background send a question to the server asking if the user name is free, and clearly signal the result of that to the user.
Having form validation done through ajax is a real user experience delight for the user if done correctly.
Of course before any of the data was saved I would definitely redo the validation server side to avoid request spoofing.
jQuery has a nice form validation plugin if you are interested. http://docs.jquery.com/Plugins/validation.
In my career, I've never gotten around having to validate server side as well as client side though.
About the storing of the list (before you persist it to the datastore). If you use ajax to validate the user name you could keep the other fields disabled until a valid user name is filled in. Don't allow the form to be posted with an invalid user name!
That would perhaps solve your problem for most cases. There is the remote possibility that someone else steals the user name while your first user is still filling in his list of books. If you want to solve that problem I suggest simply displaying the list as you got it from the request from the user. He just sent it to you, you don't have to save it anywhere else.

Can you use the django form validation functionality (which I think should just abstract all this away from you):
http://code.google.com/appengine/articles/djangoforms.html
Search in that page for "adding an item" - it handles errors automatically (which I think could include non-unique username).
Warning: also a beginner... :)

Related

filling a Django form from a separate requests.post python script

while reading about the Requests library, it occurred to me that I could try to fill a form by using it. So, since I have Django and the server, I first checked that I got the URL well and got a 200 answer code.
like this:
import requests
r = requests.get('127.0.0.1/myform')
print(r.status_code)
and yes, it was a 200
so the next step was going to be entering a value in the textfield, actually the form, for this example is just one field.
I tried this:
r = requests.post('127.0.0.1/myform', data ={'name' : 'Mexico'})
and nothing was entered. Here I have like 3 intriguing questions:
When I inspect the element, because the form was created using the ModelForm of Django, I could not actually give the field a name, (which would have been name) and 2. Django instead fills me the name with the csrf token value and 3. actually, I don't see how the requests.post presses the submit button.
What would be what is missing here in order to succeed posting the value through the form?
thank you
In Django web applications, at execution time the front end and the back end are separated and communicate over http/https requests and responses. The front end displays elements to the user, collects input, etc, but then to communicate with the back end it builds a POST request from that data and sends it when the user clicks submit. The form itself is not sent, just a collection of key value pairs corresponding to the fields of the form and the user input in each of those fields. On the back end that data is handed to the form so it can validate/save/etc.
So to answer your questions:
1) I'm not entirely sure what you are asking, but the important thing is that the post payload has a key that matches the name of the field in the corresponding Django form.
2) CSRF tokens are a security measure, and you'll have to manually account for this in your requests.post call. It may be easier to start by disabling them until you get your post working and then work on getting them working.
3) The requests.post doesn't actually press the submit button, you are just recreating the same http request that gets generated by the browser when a user presses the submit button. Does this make sense? This is a key point to understand.
Finally, in order to help you with a working solution we would need to see more. What does your form look like? What does your view look like?

Python Flask: How to stop the user from exploiting Inspect Element or to get rid of the possibility completely

I'm trying to make a chat website using python Flask. I have a route called '/chatroom', and every time a message is sent (using the HTML I'm returning in the function), the HTML also sends along a hidden field with the value of the userid back to the start of the chatroom so I can use the request.args.get function to get the userid. My problem is that anyone on the site can simply Inspect Element and change their user id located in the hidden field to get past my user removal method. Is there a way to check if Inspect Element is used by any client or to disable it? Or better yet, is it possible to not have to send the user id along in the hidden field? Here is the code for the message send field and the userid hidden field:
`'''<!DOCTYPE html>
<html>
<body>
<form action='/chatroom'>
<input type=text name='msg'>
<input type=hidden name=userid value="''',userid,'''">
</form>
</body>
</html>'''`
Every time the form is sent, like I said earlier, the program gets the 'userid' argument and assigns in to the variable userid.
I have a different method about the first time when the page loads. Just ignore that for now.
Thanks!
P.S. If the question feels vague, which it probably will, just comment on this and I can clear it up.
The problem is not really with Inspect Element - the problem is that you've built a site which is, unfortunately, insecure.
One way of handling this would be to encode and decode user IDs with each communication between the client and server. So the userid that is sent forward to the frontend (the client) is encoded and no longer looks like a regular user ID. Then when the request is sent to the server, the server decodes the ID to be able to identify the user.
This is a very simplified version of web security and isn't even close to foolproof; for example, what's to stop people just copying the encoded IDs? You could follow it up by hashing IDs, but that adds more complexity. Long story short, it's going to be touch to implement yourself, and disabling Inspect Element won't solve the problem of your site being insecure. As such, I suggest that you look into existing packages which aim to secure user identities and either use them out of the box or try to replicate their behaviour. A couple of examples to investigate are Sessions and Security - thery would be good places to start.

Save form data on every step using Django FormWizard

Background
I'm building a very large form to process customer submissions, so the end goal is to allow the user to resume the form where they left off at a later date. The form is fully functional using a FormWizard (NamedUrlSessionWizardView, actually). The Django docs mention a final save is accomplished in the done method, and leave this as an exercise to the reader. This works OK if the user completes this in one sitting, but not if you want to restore this later.
In my case, an email address is used to lookup past progress, and send a unique link to the user. This sets up the form and returns the user to where they left off. This works fine as long as your session is still valid, but not if it isn't (different computer, etc). What I would like to do is save the form data (these are ModelForms) after each step. I'll restore the user's state when they return.
Research
This answer is about the only solution I can find, but the solution is the same thing that the standard FormWizard.post() method does:
if form.is_valid():
# if the form is valid, store the cleaned data and files.
self.storage.set_step_data(self.steps.current, self.process_step(form))
self.storage.set_step_files(self.steps.current, self.process_step_files(form))
My Question
What is the proper way/place in a FormWizard to take action on, and save the form data out after each step?
You should be able to save the data directly to the ModelForm as you go along by simply writing it into the post method.
if self.steps.current == "form1":
data = self.request.POST["form1-response"]
user = CustomerModel.objects.get(id=self.request.user.id)
user.response = data
user.form_step = "form1"
user.save()
form_step, in this case, is simply a bookmark that you can use to direct the user back to the right step on their return. You should remove any already-saved fields from the done method, so they don't get overwritten.
If you do it this way, you may need to construct a dispatch method that rebuilds the management form when the user logs back in.
Alternatively, you might be able to get away with saving the user's session (or the relevant parts) into a session field on the model, then write a dispatch method for the SessionWizardView that injects the relevant information back in. I've never attempted it, but if you can get it to work, it might be preferable from an aesthetic standpoint depending on how many steps you have to cover.
Finally, if you can rely on your users not to clear their cookies and to use the same browser when they return, you can maybe cheat and set use persistent cookies.
Hopefully that will get you started. I'd be interested to see how you end up getting it to work. Good luck!

Use django to expose python functions on the web

I have not worked with Django seriously and my only experience is the tutorials on their site.
I am trying to write my own application now, and what I want is to have some sort of API. My idea is that I will later be able to use it with a client written in any other language.
I have the simplest of all apps, a model that has a name and surname field.
So the idea is that I can now write an app lets say in c++ that will send two strings to my Django app so they can be saved in the database as name, surname respectively.
What I know until now is to create a form so a user can enter that information, or have the information in the url, and of curse adding them myself from the admin menu.
What I want though is some other better way, maybe creating a packet that contains that data. Later my client sends this data to my Django webpage and it will extract the info and save it as needed. But I do not know how to do this.
If my suggested method is a good idea, then I would like an example of how this is done. If not the I would like suggestions for possible things I could try out.
Typically, as stated by #DanielRoseman, you certainly want to:
Create a REST API to get data from another web site
Get data, typically in JSON or XML, that will contain all the required data (name and surname)
In the REST controller, Convert this data to the Model and save the Model to the database
Send an answer.
More information here: http://www.django-rest-framework.org/

Django : How to count number of people viewed

I'm making a simple BBS application in Django and I want it so that whenever someone sees a post, the number of views on that post (post_view_no) is increased.
At the moment, I face two difficulties:
I need to limit the increase in post_view_no so that one user can only increase it once regardless of how many times the user refreshes/clicks on the post.
I also need to be able to track the users that are not logged in.
Regards to the first issue, it seems pretty easy as long as I create a model called 'View' and check the db but I have a feeling this may be an overkill.
In terms of second issue, all I can think of is using cookies / IP address to track the users but IP is hardly unique and I cannot figure out how to use cookies
I believe this is a common feature on forum/bbs solutions but google search only turned up with plugins or 'dumb' solutions that increase the view each time the post is viewed.
What would be the best way to go about this?
I think you can do both things via cookies. For example, when user visits a page, you can
Check if they have “viewed_post_%s” (where %s is post ID) key set in their session.
If they have, do nothing. If they don't, increase view_count numeric field of your corresponding Post object by one, and set the key (cookie) “viewed_post_%s” in their session (so that it won't count in future).
This would work with both anonymous and registered users, however by clearing cookies or setting up browser to reject them user can game the view count.
Now using cookies (sessions) with Django is quite easy: to set a value for current user, you just invoke something like
request.session['viewed_post_%s' % post.id] = True
in your view, and done. (Check the docs, and especially examples.)
Disclaimer: this is off the top of my head, I haven't done this personally, usually when there's a need to do some page view / activity tracking (so that you see what drives more traffic to your website, when users are more active, etc.) then there's a point in using a specialized system (e.g., Google Analytics, StatsD). But for some specific use case, or as an exercise, this should work.
Just to offer a secondary solution, which I think would work but is also prone to gaming (if coming by proxy or different devices). I haven't tried this either but I think it should work and wouldn't require to think about cookies, plus you aggregate some extra data which is noice.
I would make a model called TrackedPosts.
class TrackedPosts(models.Model):
post = models.ForeignKey(Post)
ip = models.CharField(max_length=16) #only accounting for ipv4
user = models.ForeignKey(User) #if you want to track logged in or anonymous
Then when you view a post, you would take the requests ip.
def my_post_view(request, post_id):
#you could check for logged in users as well.
tracked_post, created = TrackedPost.objects.get_or_create(post__pk=id, ip=request.ip, user=request.user) #note, not actual api
if created:
tracked_post.post.count += 1
tracked_post.post.save()
return render_to_response('')

Categories