aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/__init__.py3
-rw-r--r--app/forms.py28
-rw-r--r--app/models.py17
-rw-r--r--app/routes.py53
-rw-r--r--app/templates/base.html4
-rw-r--r--app/templates/index.html2
-rw-r--r--app/templates/login.html1
-rw-r--r--app/templates/register.html37
8 files changed, 132 insertions, 13 deletions
diff --git a/app/__init__.py b/app/__init__.py
index 996b683..ae7e240 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -3,11 +3,14 @@ __version__ = "0.1.0"
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
+from flask_login import LoginManager
from .config import Config
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
+login = LoginManager(app)
+login.login_view = 'login'
from app import routes, models
diff --git a/app/forms.py b/app/forms.py
index 919db70..75de178 100644
--- a/app/forms.py
+++ b/app/forms.py
@@ -1,6 +1,11 @@
+
from flask_wtf import FlaskForm
+
from wtforms import StringField, PasswordField, BooleanField, SubmitField
-from wtforms.validators import DataRequired
+from wtforms.validators import DataRequired, ValidationError, Email, EqualTo
+
+from app.models import User
+
class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
@@ -9,4 +14,25 @@ class LoginForm(FlaskForm):
submit = SubmitField("Sign In")
+class RegistrationForm(FlaskForm):
+ username = StringField("Username", validators=[DataRequired()])
+ email = StringField("Email", validators=[DataRequired(), Email()])
+ password = PasswordField("Password", validators=[DataRequired()])
+ password2 = PasswordField(
+ "Repeat Password", validators=[DataRequired(), EqualTo("password")]
+ )
+ submit = SubmitField("Register")
+
+ def validate_username(self, username):
+ user = User.query.filter_by(username=username.data).first()
+ if user is not None:
+ raise ValidationError(
+ "Username already in use, please use a different one."
+ )
+ def validate_email(self, email):
+ user = User.query.filter_by(email=email.data).first()
+ if user is not None:
+ raise ValidationError(
+ "Email address already in use, please use a different one."
+ )
diff --git a/app/models.py b/app/models.py
index 9d11ffb..b607748 100644
--- a/app/models.py
+++ b/app/models.py
@@ -1,11 +1,15 @@
import datetime
+from flask_login import UserMixin
+
+from werkzeug.security import generate_password_hash, check_password_hash
from app import db
+from app import login
-class User(db.Model):
+class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(), unique=True, nullable=False)
@@ -17,6 +21,12 @@ class User(db.Model):
def __repr__(self):
return "<User %r>" % self.username
+ def set_password(self, password):
+ self.password_hash = generate_password_hash(password)
+
+ def check_password(self, password):
+ return check_password_hash(self.password_hash, password)
+
class Dataset(db.Model):
id = db.Column(db.Integer, primary_key=True)
@@ -57,3 +67,8 @@ class Annotation(db.Model):
def __repr__(self):
return "<Annotation %r>" % self.id
+
+
+@login.user_loader
+def load_user(_id):
+ return User.query.get(int(_id))
diff --git a/app/routes.py b/app/routes.py
index 2f9d9b8..44600db 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -1,24 +1,57 @@
-from flask import render_template, flash, redirect, url_for
+
+from flask import render_template, flash, redirect, url_for, request
+from flask_login import current_user, login_user, logout_user, login_required
+
+from werkzeug.urls import url_parse
+
from app import app
-from app.forms import LoginForm
+from app import db
+from app.forms import LoginForm, RegistrationForm
+from app.models import User
@app.route("/")
@app.route("/index")
+@login_required
def index():
- user = {"username": "Gertjan"}
- return render_template("index.html", title="Home", user=user)
+ return render_template("index.html", title="Home")
@app.route("/login", methods=("GET", "POST"))
def login():
+ if current_user.is_authenticated:
+ return redirect(url_for("index"))
form = LoginForm()
if form.validate_on_submit():
- flash(
- "Login requested for user {}, remember_me={}".format(
- form.username.data, form.remember_me.data
- )
- )
- return redirect(url_for("index"))
+ user = User.query.filter_by(username=form.username.data).first()
+ if user is None or not user.check_password(form.password.data):
+ flash("Invalid username or password", category="error")
+ return redirect(url_for("login"))
+ login_user(user, remember=form.remember_me.data)
+ next_page = request.args.get("next")
+ if not next_page or url_parse(next_page).netloc != "":
+ next_page = url_for("index")
+ return redirect(next_page)
return render_template("login.html", title="Sign In", form=form)
+
+
+@app.route("/logout")
+def logout():
+ logout_user()
+ return redirect(url_for("index"))
+
+
+@app.route("/register", methods=("GET", "POST"))
+def register():
+ if current_user.is_authenticated:
+ return redirect(url_for("index"))
+ form = RegistrationForm()
+ if form.validate_on_submit():
+ user = User(username=form.username.data, email=form.email.data)
+ user.set_password(form.password.data)
+ db.session.add(user)
+ db.session.commit()
+ flash("Thank you, you are now a registered user!")
+ return redirect(url_for("login"))
+ return render_template("register.html", title="Register", form=form)
diff --git a/app/templates/base.html b/app/templates/base.html
index c40482d..3070587 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -9,7 +9,11 @@
<body>
<div>Annotate Change:
<a href="{{ url_for('index') }}">Home</a>
+ {% if current_user.is_anonymous %}
<a href="{{ url_for('login') }}">Login</a>
+ {% else %}
+ <a href="{{ url_for('logout') }}">Logout</a>
+ {% endif %}
</div>
<hr>
{% with messages = get_flashed_messages() %}
diff --git a/app/templates/index.html b/app/templates/index.html
index f111cd6..3cf36ee 100644
--- a/app/templates/index.html
+++ b/app/templates/index.html
@@ -1,5 +1,5 @@
{% extends "base.html" %}
{% block content %}
-<h1>Hi, {{ user.username }}!</h1>
+<h1>Hi, {{ current_user.username }}!</h1>
{% endblock %}
diff --git a/app/templates/login.html b/app/templates/login.html
index 21e0161..77410a1 100644
--- a/app/templates/login.html
+++ b/app/templates/login.html
@@ -21,4 +21,5 @@
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
+ <p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>
{% endblock %}
diff --git a/app/templates/register.html b/app/templates/register.html
new file mode 100644
index 0000000..487b860
--- /dev/null
+++ b/app/templates/register.html
@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <h1>Register</h1>
+ <form action="" method="post">
+ {{ form.hidden_tag() }}
+ <p>
+ {{ form.username.label }}<br>
+ {{ form.username(size=32) }}<br>
+ {% for error in form.username.errors %}
+ <span style="color: red;">[{{ error }}]</span>
+ {% endfor %}
+ </p>
+ <p>
+ {{ form.email.label }}<br>
+ {{ form.email(size=64) }}<br>
+ {% for error in form.email.errors %}
+ <span style="color: red;">[{{ error }}]</span>
+ {% endfor %}
+ </p>
+ <p>
+ {{ form.password.label }}<br>
+ {{ form.password(size=32) }}<br>
+ {% for error in form.password.errors %}
+ <span style="color: red;">[{{ error }}]</span>
+ {% endfor %}
+ </p>
+ <p>
+ {{ form.password2.label }}<br>
+ {{ form.password2(size=32) }}<br>
+ {% for error in form.password2.errors %}
+ <span style="color: red;">[{{ error }}]</span>
+ {% endfor %}
+ </p>
+ <p>{{ form.submit() }}</p>
+ </form>
+{% endblock %}