Detect users already exist in database on user registration - python

I'm writing my first web site, and am dealing with user registration.
One common problem to me like to everyone else is to detect user already exist.
I am writing the app with python, and postgres as database.
I have currently come up with 2 ideas:
1)
lock(mutex)
u = select from db where name = input_name
if u == null insert into db (name) values (input_name)
else return 'user already exist'
unlock(mutex)
2)
try: insert into db (name) values(input)
except: return 'user already exist'
The first way is to use mutex lock for clear logic, while the second way using exception to indicate user existence.
Can anyone discuss what are the pros and cons of both of the methods?

I think both will work, and both are equally bad ideas. :) My point is that implementing user authentication in python/pg has been done so many times in the past that there's hardly justification for writing it yourself. Have you had a look at Django, for example? It will take care of this for you, and much more, and let you focus your efforts on your particular application.

Slightly different, I usually do a select query via AJAX to determine if a username already exists, that way I can display a message on the UI explaining that the name is already taken and suggest another before the submit the registration form.

Related

Possible to see passwords on db browser for sqlite?

So I have a wiki site made with python using flask. In the site you have to register to submit a post. When I made my account I looked at the db file. Under users it has my username but my password looks something like this
pbkdf2:sha256:50000$trQqtDeG$fb666b434b1920c814101fd3afedf75c9e21e2eebbfe7e6aa9fe4aec3d69b1e3
I made my password poop ( dont ask why lol ) but thats what it comes up as. Lets say if I were to oneday forget my password, how can I check to see what it is?
Edit: Thanks for the explanation ! :)
You can't. This is a one way hash, and it's meant to be that way - it's a common practice not to store plaintext passwords on the database, so that nobody can ever see what is the users password.
The general concept is that given an user password (and a salt) you are able to compute the same hash value and compare it to see if the password is correct, but you are not able to (easily) get the password by obtaining the hash.
To deal with 'what if I forget my password' issue you should implement a password reset procedure.

Django: How to save a record in a new table before saving (user udates) the original

Scenario:
Developing a question answer app.
Here are different users can answer the questions.
Each question may have several fields to response (2 or 3 yes/No checkboxes) and any user can update any of those any time.
Problem:
I need to keep a log (with time and user name) in a different log table every time the records got any changes.
The log table is just a look alike of the original model (e.g. ChangeLogModel) just with 2 extra fields as logDate and ChangingUser.
This will help me to check the log and find the status of the question in any specific date.
Possible Solutions:
Using signals (...Not used to with signals, lack of detailed tutorials, documentation is not detailed too)
making the backup before doing any ".save()" (... Have o idea how to do that)
Install any external app (...Trying to avoid installing any app)
Summary:
Basically What I am asking for is a log table where the 'state' of the original record/row/tuple would be saved to another table (i.e. logTable) prior to hit the "form.save()" trigger.
So, every time the record got updated so the LogTable will get a new row with a datestamp.
You could use an django package for audit and history, any of those in this overview for example.
I had success using django-simple-history.
I think that the best way is just to do it straight forward. You can save the user's answer and right after that the log, wrap it with database transaction and rollback if something goes wrong.
Btw if the logs table has the same fields like the original model you might consider using foreign key or inheritance, depends on your program logic.

how to prevent multiple votes from a single user

I am writing a web app on google app engine with python. I am using jinja2 as a templating engine.
I currently have it set up so that users can upvote and downvote posts but right now they can vote on them as many times as they would like. I simply have the vote record in a database and then calculate it right after that. How can I efficiently prevent users from casting multiple votes?
I suggest making a toggleVote method, which accepts the key of the item you want to toggle the vote on, and the key of the user making the vote.
I'd also suggest adding a table to record the votes, basically containing two fields:
"keyOfUserVoting", "keyOfItemBeingVotedOn"
That way you can simply do a very query where the keys match, and if an item exists, then you know the user voted on that item. (Query where keyOfUserVoting = 'param1' and keyOfItemVoted='param2', if result != None, then it means the user voted)
For the toggleVote() method the case could be very simple:
toggleVote(keyOfUserVoting, keyOfItemToVoteOn):
if (queryResultExists):
// delete this record from the 'votes' table
else:
// add record to the 'votes' table
That way you'll never have to worry about keeping track on an individual basis of how many times the user has voted or not.
Also this way, if you want to find out how many votes are on an item, you can do another query to quickly count where keyOfItemToVoteOn = paramKeyOfItem. Again, with GAE, this will be very fast.
In this setup, you can also quickly tell how many times a user has voted on one item (count where userKey = value and where itemKey = value), or how many times a user has voted in the entire system (count where userKey = value)...
Lastly, for best reliability, you can wrap the updates in the toggleVote() method in a transaction, especially if you'll be doing other things on the user or item being voted on.
Hope this helps.
Store the voting user with the vote, and check for an existing vote by the current user, using your database.
You can perform the check either before you serve the page (and so disable your voting buttons), or when you get the vote attempt (and show some kind of message). You should probably write code to handle both scenarios if the voting really matters to you.

Server side form validation and POST data

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... :)

Authenticating on Web.py - will this code be unsafe for production?

I am making a simple web-app which requires login for the admin page. I came across this incantation on the web.py site (http://webpy.org/cookbook/userauth) :
import hashlib
import web
def POST(self):
i = web.input()
authdb = sqlite3.connect('users.db')
pwdhash = hashlib.md5(i.password).hexdigest()
check = authdb.execute('select * from users where username=? and password=?', (i.username, pwdhash))
if check:
session.loggedin = True
session.username = i.username
raise web.seeother('/results')
else: return render.base("Those login details don't work.")
However the page also gives a somewhat ominous warning: "Do not use this code on real site - this is only for illustration.". I was wondering if there are any major holes in this, I'm somewhat unfamiliar with web-programming so just wanted to make sure that using this code wont unwittingly make the app open to trivial attack vectors?
Many thanks
select * from users where username=? and password=?', (i.username, pwdhash)
^ SQL injection, broseph. If someone does 'or 1=1' into the search field, they'll get the first result in users because of the SELECT * from. Often the first entry is the admin credentials.
The only glaringly obvious problem I see is that the password is stored with as simple MD5 hash with no salt. From your point of view, this isn't so much of an issue, but from the user's point of view it's a major security flaw since someone with access to the database can fairly easily crack sufficiently bad passwords by just googling their MD5 hashes.
The only possible problem I can think of here, could be if it would somehow be possible to exploit MD5 collisions, i.e. that two different strings can generate the same MD5 hash - in that case someone could potentially log in with a password that is not correct, but generates the same MD5 hash.
Changing to a better hashing algorithm such as SHA-1 (or something else available in hashlib) would close this potential security problem.
As far as I know, it would be very difficult to exploit the MD5 collision problem to gain access. Even so, it is broken, and quoting security guru Bruce Schneier from the wikipedia article:
[he] wrote of the attack that "[w]e already knew that MD5 is a broken hash function" and that "no one should be using MD5 anymore."

Categories