sign up feature added

This commit is contained in:
iou1name 2018-06-16 16:42:31 -04:00
parent 48254e98bf
commit b3ba10fae2
4 changed files with 168 additions and 1 deletions

View File

@ -4,7 +4,9 @@ Simple file host using Flask.
""" """
import os import os
import time import time
import string
import urllib import urllib
import functools
from flask import Flask, session, request, abort, redirect, url_for, g, \ from flask import Flask, session, request, abort, redirect, url_for, g, \
render_template render_template
@ -12,6 +14,7 @@ from flask_socketio import SocketIO, emit, join_room
from flask_paranoid import Paranoid from flask_paranoid import Paranoid
import MySQLdb import MySQLdb
import bleach import bleach
from passlib.hash import argon2
class ReverseProxied(object): class ReverseProxied(object):
""" """
@ -97,6 +100,77 @@ def init():
db_execute(cmd) db_execute(cmd)
def login_required(url=None):
"""
A decorator function to protect certain endpoints by requiring the user
to either pass a valid session cookie, or pass thier username and
password along with the request to login.
"""
def actual_decorator(func):
@functools.wraps(func)
def _nop(*args, **kwargs):
username = session.get("username")
if verify_username(username):
return func(*args, **kwargs)
username = request.form.get("user")
password = request.form.get("pass")
if verify_password(username, password):
return func(*args, **kwargs)
if url:
return redirect(url_for(url))
else:
abort(401)
return _nop
return actual_decorator
def add_user(username, password):
"""
Adds a user to the database.
"""
if verify_username(username): # username taken
return "username_taken"
elif len(username) > 20:
return "username_too_long"
pw_hash = argon2.hash(password)
db_execute(
"INSERT INTO `users` (`username`, `password_hash`) VALUES (%s, %s)",
(username, pw_hash))
return "success"
def verify_password(username, password):
"""
Verifies a user's password.
"""
user = verify_username(username)
if not user:
return False
user_id, _, pw_hash = user
if argon2.verify(password, pw_hash):
session["user_id"] = user_id
return True
else:
return False
def verify_username(username):
"""
Checks to see if the given username is in the database.
"""
user = db_execute("SELECT * FROM `users` WHERE `username` = %s",
(username,)).fetchone()
if user:
return user
else:
return False
@socketio.on('joined', namespace="/chat") @socketio.on('joined', namespace="/chat")
def joined(data): def joined(data):
""" """
@ -156,6 +230,7 @@ def quest(quest_title):
@app.route("/create_quest", methods=["GET", "POST"]) @app.route("/create_quest", methods=["GET", "POST"])
@login_required("login")
def create_quest(): def create_quest():
""" """
Starts a new quest. Starts a new quest.
@ -175,6 +250,58 @@ def create_quest():
return redirect(url_for('quest', quest_title=ident_title)) return redirect(url_for('quest', quest_title=ident_title))
@app.route("/login", methods=["GET", "POST"])
def login():
"""
Logs the user in.
"""
if request.method == "GET":
return render_template("login.html")
username = request.form.get("user")
password = request.form.get("pass")
if verify_password(username, password):
session["username"] = username
return redirect(url_for("index"))
else:
abort(401)
@app.route("/signup", methods=["GET", "POST"])
def signup():
"""
Create a new account.
"""
if request.method == "GET":
return render_template("signup.html")
username = request.form.get("user")
password = request.form.get("pass")
verify_password = request.form.get("verify_pass")
if len(username) > 20:
"username_too_long"
elif len(username) < 3:
"username_too_short"
chrs = [c not in string.ascii_letters + string.digits for c in username]
if any(chrs):
"username_bad_chars"
if verify_username(username):
"username_taken"
if len(password) > 1024:
"password_too_long"
elif len(password) < 8:
"password_too_short"
if password != verify_password:
"passwords_dont_match"
res = add_user(username, password)
return redirect(url_for("index"))
@app.route("/") @app.route("/")
def index(): def index():
""" """

View File

@ -6,6 +6,8 @@
<body> <body>
<h1>Quests 'n Shiet</h1> <h1>Quests 'n Shiet</h1>
<a href="./quest/unga-bunga-quest">Unga Bunga Quest</a><br /> <a href="./quest/unga-bunga-quest">Unga Bunga Quest</a><br />
<a href="./create_quest">Create New Quest</a> <a href="./create_quest">Create New Quest</a><br />
<a href="./signup">Sign up</a><br />
<a href="./login">Login</a><br />
</body> </body>
</html> </html>

13
templates/login.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<form method="post" action="{{ url_for('login') }}">
<input type="text" placeholder="Username" name="user" maxlength="20" required/><br />
<input type="password" placeholder="Password" name="pass" maxlength="1024" required/><br />
<input type="submit" value="Log in" name="submit"/>
</form>
</body>
</html>

25
templates/signup.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Sign up a new account</title>
</head>
<body>
<div id="namePassRules">
<p>Username rules:
<ul>
<li>Must be between 3 and 20 characters</li>
<li>Can only contain ASCII letters (case sensitive) and numbers</li>
</ul>
<p>Password rules:
<ul>
<li>Must be between 8 and 1024 characters</li>
</ul>
<form method="post" action="{{ url_for('signup') }}">
<input type="text" placeholder="Username" name="user" maxlength="20" required/><br />
<input type="password" placeholder="Password" name="pass" maxlength="1024" required/><br />
<input type="password" placeholder="Verify password" name="verify_pass" maxlength="1024" required/><br />
<input type="submit" value="Sign up" name="submit"/>
</form>
</body>
</html>