Compare commits
1 Commits
2435d015fc
...
b3ba10fae2
Author | SHA1 | Date | |
---|---|---|---|
b3ba10fae2 |
127
anonkun.py
127
anonkun.py
|
@ -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():
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
13
templates/login.html
Normal 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
25
templates/signup.html
Normal 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>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user