summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorstilbruch <stilbruch@protonmail.com>2022-03-23 12:30:23 -0500
committerstilbruch <stilbruch@protonmail.com>2022-03-23 12:30:23 -0500
commitc57ebef076438c83a0e408227341398249566ff1 (patch)
treed4e943e771a127d285baaee14867f48040f23c8d /app
parent43755d0b6d1f65fd65862454be81bd0f5d7ff7dd (diff)
downloadStrengthy-c57ebef076438c83a0e408227341398249566ff1.tar.xz
Strengthy-c57ebef076438c83a0e408227341398249566ff1.zip
User registration and login now works
Diffstat (limited to 'app')
-rw-r--r--app/app.py10
-rw-r--r--app/database.py19
-rw-r--r--app/forms.py13
-rw-r--r--app/login.py55
-rw-r--r--app/routes.py56
-rw-r--r--app/tables/user.py25
-rw-r--r--app/templates/user/login.html16
-rw-r--r--app/templates/user/register.html21
8 files changed, 120 insertions, 95 deletions
diff --git a/app/app.py b/app/app.py
index 8f6fafe..3051934 100644
--- a/app/app.py
+++ b/app/app.py
@@ -1,16 +1,24 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
+from flask_login import LoginManager
# Setup app before doing imports
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.config['SECRET_KEY'] = "super duper secret" # FIXME: do not use in prod
-app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://../strenghty.db'
+app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../strengthy.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
+# Setup flask-login
+login_manager = LoginManager(app)
+login_manager.init_app(app)
+
# Setup SQLAlchemy
# https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/#a-minimal-application
db = SQLAlchemy(app)
+# TODO: do in script
+import tables.user
+db.create_all()
# Load routes
import routes
diff --git a/app/database.py b/app/database.py
deleted file mode 100644
index e23aa5d..0000000
--- a/app/database.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import sqlite3
-from app import app
-from flask import g
-
-# constants
-DATABASE_FILE = "../strengthy.db"
-
-# Called when an "appcontext" is closed, usually a request is finished
-@app.teardown_appcontext
-def close_db_conn(exception):
- db = getattr(g, '_database', None)
- if db is not None:
- db.close()
-
-def database_get():
- db = getattr(g, '_database', None)
- if db is None:
- db = g._database = sqlite3.connect(DATABASE_FILE)
- return db
diff --git a/app/forms.py b/app/forms.py
new file mode 100644
index 0000000..12e4bf8
--- /dev/null
+++ b/app/forms.py
@@ -0,0 +1,13 @@
+from flask_wtf import FlaskForm
+from wtforms import StringField, PasswordField, BooleanField
+from wtforms.validators import DataRequired, Email
+
+class LoginForm(FlaskForm):
+ username = StringField("username", validators=[DataRequired()])
+ password = PasswordField("password", validators=[DataRequired()])
+ #remember_me = BooleanField()
+
+class RegisterForm(FlaskForm):
+ username = StringField("username", validators=[DataRequired()])
+ password = PasswordField("password", validators=[DataRequired()])
+ email = StringField("email", validators=[DataRequired(), Email()])
diff --git a/app/login.py b/app/login.py
deleted file mode 100644
index 6d4b4a2..0000000
--- a/app/login.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from app import app
-from database import database_get
-from flask_login import LoginManager, UserMixin, current_user
-from flask_wtf import FlaskForm
-from wtforms import StringField, PasswordField, BooleanField
-from wtforms.validators import DataRequired, Email
-
-# https://python.plainenglish.io/implementing-flask-login-with-hash-password-888731c88a99
-
-# Forms classes for flask_wtf
-class LoginForm(FlaskForm):
- username = StringField("username", validators=[DataRequired()])
- password = PasswordField("password", validators=[DataRequired()])
- remember_me = BooleanField()
-
-class RegisterForm(FlaskForm):
- username = StringField("username", validators=[DataRequired()])
- password = PasswordField("password", validators=[DataRequired()])
- name = StringField("name")
- email = StringField("email", validators=[DataRequired(), Email()])
-
-# User class for flask_login
-class User(UserMixin):
- def __init__(self, id, email, password_hash):
- self.id = unicode(id)
- self.email = email
- self.password_hash = password_hash
- self.authenticated = False
-
- def is_authenticated(self):
- return self.authenticated
-
- def is_active(self):
- return True
-
- def is_anonymous(self):
- return False
-
- def get_id(self):
- return self.id
-
-login_manager = LoginManager()
-login_manager.init_app(app)
-
-@login_manager.user_loader
-def load_user(uid):
- conn = database_get()
- curs = conn.cursor()
- curs.execute("SELECT * FROM users WHERE id = (?)", [uid])
- row = curs.fetchone()
-
- if row is None:
- return None
- else:
- return User(int(row[0]), row[1], row[2])
diff --git a/app/routes.py b/app/routes.py
index fdf65e3..ca556ad 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -1,20 +1,56 @@
-from app import app
-from database import database_get
-from flask import render_template
-from login import *
+from app import app, db
+from flask import render_template, redirect, url_for, flash
+from flask_login import login_user
+from forms import LoginForm, RegisterForm
+from tables.user import User
@app.route("/", methods=["GET"])
def index():
return render_template('base/index.html')
-@app.route("/login", methods=["GET"])
+@app.route("/home", methods=["GET"])
+def home():
+ return render_template('base/home.html')
+
+@app.route("/login", methods=['GET', 'POST'])
def login():
- return render_template('user/login.html')
+ form = LoginForm()
+ username = form.username.data
+ password = form.password.data
+
+ if form.validate_on_submit():
+ # Valid submission
+ user = User.query.filter_by(username=username).first()
+
+ # TODO: show user if login succeeded
+ if user and user.verify_password(password):
+ login_user(user)
+ return redirect(url_for('home'))
+ else:
+ flash("invalid login")
+ return redirect(url_for('register'))
-@app.route("/register", methods=["GET"])
+ return render_template('user/login.html', form=form)
+
+@app.route("/register", methods=['GET', 'POST'])
def register():
form = RegisterForm()
+ # Load data from form
+ username = form.username.data
+ password = form.password.data
+ email = form.email.data
+
+ print("register")
+
+ if form.validate_on_submit():
+ # Valid submission
+ user = User.query.filter_by(username=username).first()
+ if not user:
+ # No user with this username
+ user = User(username, password, email)
+ db.session.add(user)
+ db.session.commit()
- #if form.validate_on_submit():
- # # TODO: make sure username isnt taken somehow
- return render_template('user/register.html')
+ return redirect(url_for('login'))
+ else:
+ return render_template('user/register.html', form=form)
diff --git a/app/tables/user.py b/app/tables/user.py
new file mode 100644
index 0000000..d384fdb
--- /dev/null
+++ b/app/tables/user.py
@@ -0,0 +1,25 @@
+from app import db, login_manager
+from flask_login import UserMixin
+from werkzeug.security import generate_password_hash, check_password_hash
+
+@login_manager.user_loader
+def get_user(user_id):
+ return User.query.get(user_id)
+
+class User(db.Model, UserMixin):
+ __tablename__ = 'users'
+ id = db.Column(db.Integer, primary_key=True)
+ username = db.Column(db.String(80), unique=True, nullable=False)
+ password = db.Column(db.String(80))
+ email = db.Column(db.String(120), unique=True, nullable=False)
+
+ def __init__(self, username, password, email):
+ self.username = username
+ self.password = generate_password_hash(password)
+ self.email = email
+
+ def __repr__(self):
+ return f'<User {self.username}>'
+
+ def verify_password(self, pwd):
+ return check_password_hash(self.password, pwd)
diff --git a/app/templates/user/login.html b/app/templates/user/login.html
index 7a671c1..9aaf33c 100644
--- a/app/templates/user/login.html
+++ b/app/templates/user/login.html
@@ -3,26 +3,30 @@
{% block content %}
<div class="login">
<div class="form">
- <section class="hero is-primary is-fullheight">
+ <section class="hero is-primary is-fullheight-with-navbar">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-5-tablet is-4-desktop is-3-widescreen">
<h1 class="title is-2">Log in</h1>
- <form action="" class="box">
+
+ <!-- TODO: render errors -->
+
+ <form method="POST" class="box">
+ {{ form.csrf_token }}
<div class="field">
- <label for="" class="label">Email</label>
+ <label for="" class="label">Username</label>
<div class="control has-icons-left">
- <input type="email" placeholder="e.g. bobsmith@gmail.com" class="input" required>
+ <input id="username" name="username" type="text" class="input" required>
<span class="icon is-small is-left">
- <i class="fa fa-envelope"></i>
+ <i class="fa fa-user"></i>
</span>
</div>
</div>
<div class="field">
<label for="" class="label">Password</label>
<div class="control has-icons-left">
- <input type="password" placeholder="*******" class="input" required>
+ <input id="password" name="password" type="password" placeholder="*******" class="input" required>
<span class="icon is-small is-left">
<i class="fa fa-lock"></i>
</span>
diff --git a/app/templates/user/register.html b/app/templates/user/register.html
index dc61204..6341671 100644
--- a/app/templates/user/register.html
+++ b/app/templates/user/register.html
@@ -3,17 +3,30 @@
{% block content %}
<div class="register">
<div class="form">
- <section class="hero is-primary is-fullheight">
+ <section class="hero is-primary is-fullheight-with-navbar">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-5-tablet is-4-desktop is-3-widescreen">
<h1 class="title is-2">Sign up</h1>
- <form action="" class="box">
+
+ <!-- TODO: render errors -->
+
+ <form method="POST" class="box">
+ {{ form.csrf_token }}
+ <div class="field">
+ <label for="" class="label">Username</label>
+ <div class="control has-icons-left">
+ <input id="username" name="username" type="text" placeholder="e.g. gymdude99" class="input" required>
+ <span class="icon is-small is-left">
+ <i class="fa fa-user"></i>
+ </span>
+ </div>
+ </div>
<div class="field">
<label for="" class="label">Email</label>
<div class="control has-icons-left">
- <input type="email" placeholder="e.g. bobsmith@gmail.com" class="input" required>
+ <input id="email" name="email" type="email" placeholder="e.g. bobsmith@gmail.com" class="input" required>
<span class="icon is-small is-left">
<i class="fa fa-envelope"></i>
</span>
@@ -22,7 +35,7 @@
<div class="field">
<label for="" class="label">Password</label>
<div class="control has-icons-left">
- <input type="password" placeholder="*******" class="input" required>
+ <input id="password" name="password" type="password" placeholder="*******" class="input" required>
<span class="icon is-small is-left">
<i class="fa fa-lock"></i>
</span>