diff --git a/app.py b/app.py index f48ae01..f01d1f0 100644 --- a/app.py +++ b/app.py @@ -6,11 +6,14 @@ import click import pytz from faker import Faker from flask import Flask, render_template, request +from flask_wtf.csrf import CSRFProtect, CSRFError from flask_login import LoginManager, current_user from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash from database import db +csrf = CSRFProtect() + def create_app(): app = Flask(__name__) @@ -27,6 +30,7 @@ def create_app(): app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', '').replace('postgres://', 'postgresql://', 1) db.init_app(app) + csrf.init_app(app) login_manager = LoginManager() login_manager.login_view = 'auth.login' @@ -52,6 +56,10 @@ def create_app(): # note that we set the 404 status explicitly return render_template('errors/404.html'), 404 + @app.errorhandler(CSRFError) + def handle_csrf_error(e): + return render_template('errprs/csrf.html', reason=e.description), 400 + @app.before_request def update_last_seen(): if current_user.is_authenticated: diff --git a/forms.py b/forms.py index 4478136..66c3d12 100644 --- a/forms.py +++ b/forms.py @@ -1,9 +1,10 @@ -from wtforms import Form, BooleanField, StringField, PasswordField, TextAreaField, validators +from flask_wtf import FlaskForm +from wtforms import BooleanField, StringField, PasswordField, TextAreaField, validators from validators import NoProfanity -class RegistrationForm(Form): +class RegistrationForm(FlaskForm): username = StringField('Username', [validators.Length(min=4, max=25), NoProfanity()]) name = StringField('Name', [validators.Length(min=2, max=35), NoProfanity()]) password = PasswordField('New Password', [ @@ -14,20 +15,20 @@ class RegistrationForm(Form): accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()]) -class LoginForm(Form): +class LoginForm(FlaskForm): username = StringField('Username', [validators.DataRequired()]) password = StringField('Password', [validators.DataRequired()]) remember_me = BooleanField('Remember Me', [validators.Optional()]) -class EditProfileForm(Form): +class EditProfileForm(FlaskForm): name = RegistrationForm.name - about_me = StringField('About Me', [validators.Optional(), NoProfanity()], description='Tell us about yourself',) + about_me = TextAreaField('About Me', [validators.Optional(), NoProfanity()], description='Tell us about yourself',) -class NewPostForm(Form): +class NewPostForm(FlaskForm): text = TextAreaField('Text', [validators.Length(min=15, max=1000), NoProfanity()], description='Express yourself.') -class NewCommentForm(Form): +class NewCommentForm(FlaskForm): text = StringField('Text', [validators.Length(min=5, max=50), NoProfanity()]) diff --git a/templates/errors/csrf.html b/templates/errors/csrf.html new file mode 100644 index 0000000..808f679 --- /dev/null +++ b/templates/errors/csrf.html @@ -0,0 +1,19 @@ +{% extends 'layouts/index.html' %} + +{% block content %} +
+
+

400 - Bad CSRF Token

+

+ {% if current_user.is_authenticated %} + Sorry {{ current_user.username }}, the + {% else %} + The + {% endif %} form you submitted requires a CSRF token to be valid. +
+ This may happen if the form was submitted long after the token was generated, and it has thus expired. + Go home? +

+
+
+{% endblock %}