mirror of
https://github.com/jackeilles/xygt.git
synced 2024-11-21 22:32:39 +01:00
functioning user login and register system
This commit is contained in:
parent
a567c7cb9b
commit
40ab9fdbb1
10 changed files with 200 additions and 6 deletions
|
@ -1,5 +1,15 @@
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
from flask_login import LoginManager
|
||||||
|
from flask_wtf.csrf import CSRFProtect
|
||||||
|
from flask_bcrypt import Bcrypt
|
||||||
|
from config import Config
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.config['SECRET_KEY'] = Config.secretKey
|
||||||
|
csrf = CSRFProtect(app)
|
||||||
|
bcrypt = Bcrypt(app)
|
||||||
|
loginManager = LoginManager(app)
|
||||||
|
loginManager.login_view = 'login'
|
||||||
|
loginManager.login_message_category = 'info'
|
||||||
|
|
||||||
from app import routes
|
from app import routes
|
23
app/models.py
Normal file
23
app/models.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from flask_login import UserMixin
|
||||||
|
from config import Config
|
||||||
|
|
||||||
|
class User(UserMixin):
|
||||||
|
def __init__(self, user, userid, password, idpass, level):
|
||||||
|
self.user = user
|
||||||
|
self.password = password
|
||||||
|
self.userid = userid
|
||||||
|
self.idpass = idpass
|
||||||
|
self.level = level
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"User('{self.user}', '{self.userid}', '{self.password}', '{self.idpass}', '{self.level}')"
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return str(self.userid)
|
||||||
|
|
||||||
|
def get(userid):
|
||||||
|
userData = Config.users.find_one({"userid": userid})
|
||||||
|
if not userData:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return User(userData["user"], userData["userid"], userData["password"], userData["idpass"], userData["level"])
|
|
@ -1,6 +1,11 @@
|
||||||
from app import app, worker
|
from app import app, worker, bcrypt, loginManager
|
||||||
|
from app.models import User
|
||||||
from config import Config, Errors
|
from config import Config, Errors
|
||||||
from flask import render_template, request, send_file, redirect
|
from flask import render_template, request, send_file, redirect, flash
|
||||||
|
from flask_login import login_user, current_user, logout_user, login_required
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, PasswordField, SubmitField, BooleanField
|
||||||
|
from wtforms.validators import DataRequired, Length, EqualTo
|
||||||
from werkzeug.datastructures import FileStorage
|
from werkzeug.datastructures import FileStorage
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
@ -9,11 +14,34 @@ import io
|
||||||
import random
|
import random
|
||||||
import magic
|
import magic
|
||||||
|
|
||||||
|
class RegistrationForm(FlaskForm):
|
||||||
|
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=16)])
|
||||||
|
password = PasswordField('Password', validators=[DataRequired(), Length(min=8, max=32)])
|
||||||
|
password2 = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
|
||||||
|
tnc = BooleanField('I agree to the Terms and Conditions', validators=[DataRequired()])
|
||||||
|
submit = SubmitField('Register')
|
||||||
|
|
||||||
|
def validate_username(self, username):
|
||||||
|
user = Config.users.find_one({"username": username.data})
|
||||||
|
if user:
|
||||||
|
raise ValueError("That username is taken. Try another.")
|
||||||
|
|
||||||
|
class LoginForm(FlaskForm):
|
||||||
|
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=16)])
|
||||||
|
password = PasswordField('Password', validators=[DataRequired(), Length(min=8, max=32)])
|
||||||
|
submit = SubmitField('Login')
|
||||||
|
|
||||||
|
@loginManager.user_loader
|
||||||
|
def load_user(userid):
|
||||||
|
user = User.get(userid)
|
||||||
|
return user
|
||||||
|
|
||||||
@app.route('/', methods=["GET", "POST"])
|
@app.route('/', methods=["GET", "POST"])
|
||||||
def index():
|
def index():
|
||||||
|
|
||||||
# Check for a GET or POST request
|
# Check for a GET or POST request
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
|
print(current_user.is_authenticated)
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
|
@ -95,4 +123,52 @@ def getInfo(id):
|
||||||
|
|
||||||
@app.route('/teapot')
|
@app.route('/teapot')
|
||||||
def teapot():
|
def teapot():
|
||||||
return 'I\'m a teapot. 418.', 418
|
return 'I\'m a teapot. 418.', 418
|
||||||
|
|
||||||
|
@app.route('/register', methods=["GET", "POST"])
|
||||||
|
def register():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect("/")
|
||||||
|
else:
|
||||||
|
if request.method == "GET":
|
||||||
|
return render_template("register.html", form=RegistrationForm())
|
||||||
|
elif request.method == "POST":
|
||||||
|
username = request.form.get("username")
|
||||||
|
password = request.form.get("password")
|
||||||
|
|
||||||
|
res = worker.registerUser(username, password)
|
||||||
|
|
||||||
|
if res == True:
|
||||||
|
flash("Successfully registered!", "success")
|
||||||
|
return redirect("/login")
|
||||||
|
else:
|
||||||
|
flash("Something went wrong, sorry.", "danger")
|
||||||
|
return redirect("/register")
|
||||||
|
|
||||||
|
@app.route('/login', methods=["GET", "POST"])
|
||||||
|
def login():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect("/")
|
||||||
|
else:
|
||||||
|
if request.method == "GET":
|
||||||
|
return render_template("login.html", form=LoginForm())
|
||||||
|
elif request.method == "POST":
|
||||||
|
username = request.form.get("username")
|
||||||
|
password = request.form.get("password")
|
||||||
|
|
||||||
|
userid = Config.users.find_one({"user": username})["userid"]
|
||||||
|
user = User.get(userid)
|
||||||
|
|
||||||
|
if user and bcrypt.check_password_hash(user.password, password):
|
||||||
|
login_user(user)
|
||||||
|
print(current_user.is_authenticated)
|
||||||
|
flash("Successfully logged in!", "success")
|
||||||
|
return redirect("/")
|
||||||
|
else:
|
||||||
|
flash("Incorrect username or password.", "danger")
|
||||||
|
return redirect("/login")
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
return redirect("/")
|
12
app/templates/base.html
Normal file
12
app/templates/base.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta ref="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>xygt.cc - {{ title }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1 +1,12 @@
|
||||||
Under Construction - No frontend available yet.
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Home</h1>
|
||||||
|
<!-- Check if the user is logged in -->
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<p>Welcome, {{ current_user.user }}!</p>
|
||||||
|
<p><a href="{{ url_for('logout') }}">Logout</a></p>
|
||||||
|
{% else %}
|
||||||
|
<p><a href="{{ url_for('login') }}">Login</a></p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
21
app/templates/login.html
Normal file
21
app/templates/login.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form action="" method="post">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
{% for field in form %}
|
||||||
|
<p>
|
||||||
|
{{ field.label }}<br>
|
||||||
|
{{ field() }}
|
||||||
|
{% if field.errors %}
|
||||||
|
<ul class=errors>
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<li class="{{ category }}">{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
21
app/templates/register.html
Normal file
21
app/templates/register.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Register</h1>
|
||||||
|
<form action="" method="post">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
{% for field in form %}
|
||||||
|
<p>
|
||||||
|
{{ field.label }}<br>
|
||||||
|
{{ field() }}
|
||||||
|
{% if field.errors %}
|
||||||
|
<ul class=errors>
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -1,4 +1,6 @@
|
||||||
from config import disallowedMimeTypes, Errors, Config
|
from config import disallowedMimeTypes, Errors, Config
|
||||||
|
from app.models import User
|
||||||
|
from app import bcrypt
|
||||||
import secrets
|
import secrets
|
||||||
import datetime
|
import datetime
|
||||||
import random
|
import random
|
||||||
|
@ -67,7 +69,6 @@ def shortenURL(url, ip, userid, id, retention):
|
||||||
while True: # Loop to find an available file ID
|
while True: # Loop to find an available file ID
|
||||||
id = randomHex() # Prevent conflicts if 2 of the same get made
|
id = randomHex() # Prevent conflicts if 2 of the same get made
|
||||||
if Config.files.find_one({'id': id}) is None:
|
if Config.files.find_one({'id': id}) is None:
|
||||||
filename = id
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if userid == None:
|
if userid == None:
|
||||||
|
@ -108,3 +109,17 @@ def idInfo(id):
|
||||||
def randomHex():
|
def randomHex():
|
||||||
hexRand = ''.join(secrets.choice('0123456789abcdef') for _ in range(6))
|
hexRand = ''.join(secrets.choice('0123456789abcdef') for _ in range(6))
|
||||||
return hexRand
|
return hexRand
|
||||||
|
|
||||||
|
def registerUser(username, password):
|
||||||
|
# Initialise some values
|
||||||
|
try:
|
||||||
|
level = 1
|
||||||
|
userid = randomHex()
|
||||||
|
idpass = bcrypt.generate_password_hash(randomHex()).decode("utf-8")
|
||||||
|
password = bcrypt.generate_password_hash(password).decode("utf-8")
|
||||||
|
user = User(username, userid, password, idpass, level)
|
||||||
|
Config.users.insert_one(user.__dict__)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
|
import random
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
# MongoDB init stuff
|
# MongoDB init stuff
|
||||||
|
@ -16,6 +17,7 @@ class Config:
|
||||||
minretention = 7
|
minretention = 7
|
||||||
fileDir = "./data"
|
fileDir = "./data"
|
||||||
ipLogEnabled = False
|
ipLogEnabled = False
|
||||||
|
secretKey = "CHANGEINPRODUCTION"
|
||||||
|
|
||||||
quotes = {
|
quotes = {
|
||||||
"Anon /g/": "Biometrics are shit, you lose a limb and you're fucked.",
|
"Anon /g/": "Biometrics are shit, you lose a limb and you're fucked.",
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
flask
|
flask
|
||||||
flask-dotenv
|
flask-dotenv
|
||||||
pymongo
|
pymongo
|
||||||
python-magic
|
python-magic
|
||||||
|
flask-login
|
||||||
|
flask-bcrypt
|
||||||
|
flask-wtf
|
Loading…
Reference in a new issue