adds email login and registration forms

- using flask-wtf forms to create login and registration
- saves and compares input data with database
- generates user if need-be
- same user form as google user
This commit is contained in:
Raphael Maenle 2020-04-23 17:11:23 +00:00
parent f156d38739
commit a071193959
8 changed files with 150 additions and 16 deletions

BIN
app.db

Binary file not shown.

31
server/forms.py Normal file
View File

@ -0,0 +1,31 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, ValidationError, Email, EqualTo
from server.models import User
import email_validator
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
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('Please use a different username.')
def validate_email(self, email):
user = User.query.filter_by(email=email.data).first()
if user is not None:
raise ValidationError('Please use a different email address.')

View File

@ -1,12 +1,13 @@
from flask_login import UserMixin from flask_login import UserMixin
from server import login_manager, db from server import login_manager, db
from werkzeug.security import generate_password_hash, check_password_hash
@login_manager.user_loader @login_manager.user_loader
def load_user(id): def load_user(id):
return User.query.get(id) return User.query.get(id)
class User(UserMixin, db.Model): class User(UserMixin, db.Model):
id = db.Column(db.String(21), primary_key=True) id = db.Column(db.String(64), primary_key=True)
username = db.Column(db.String(64), index=True, unique=True) username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True)
profile_pic = db.Column(db.String(256)) profile_pic = db.Column(db.String(256))
@ -15,6 +16,12 @@ class User(UserMixin, db.Model):
def __repr__(self): def __repr__(self):
return '<User {}>'.format(self.username) return '<User {}>'.format(self.username)
def setPassword(self, password):
self.password_hash = generate_password_hash(password)
def checkPassword(self, password):
return check_password_hash(self.password_hash, password)
class Calendar(db.Model): class Calendar(db.Model):
usr_id = db.Column(db.String(21), index=True) usr_id = db.Column(db.String(21), index=True)
calendar_id = db.Column(db.String(256), primary_key=True) calendar_id = db.Column(db.String(256), primary_key=True)

View File

@ -5,6 +5,7 @@ import sqlite3
# Third-party libraries # Third-party libraries
import flask import flask
from flask import render_template, flash
from flask import Flask, redirect, request, url_for from flask import Flask, redirect, request, url_for
from flask_login import ( from flask_login import (
LoginManager, LoginManager,
@ -18,6 +19,7 @@ import requests
import server.googleHandler as google import server.googleHandler as google
from server import login_manager, app, db from server import login_manager, app, db
from server.forms import LoginForm, RegistrationForm
from server.models import User, Calendar from server.models import User, Calendar
@app.route("/") @app.route("/")
@ -41,8 +43,39 @@ def calendar():
calendars = google.calendarsFromDb() calendars = google.calendarsFromDb()
return flask.render_template('calendar.html', calendars=calendars) return flask.render_template('calendar.html', calendars=calendars)
@app.route('/login/email', methods=['GET', 'POST'])
def emaillogin():
if current_user.is_authenticated:
return redirect(url_for('account') )
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.checkPassword(form.password.data):
flash('invalid username or password')
return redirect(url_for('emaillogin'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('account'))
return render_template('emaillogin.html', title='Sign In', form=form)
@app.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('account'))
form = RegistrationForm()
if form.validate_on_submit():
user = User(id=form.username.data,
username=form.username.data,
email=form.email.data)
user.setPassword(form.password.data)
db.session.add(user)
db.session.commit()
flash('Congratulations, you are now a registered user!')
return redirect(url_for('emaillogin'))
return render_template('register.html', title='Register', form=form)
@app.route("/login/google") @app.route("/login/google")
def login(): def googlelogin():
authorization_url = google.login() authorization_url = google.login()
return flask.redirect(authorization_url) return flask.redirect(authorization_url)
@ -121,4 +154,3 @@ def user():
print("405") print("405")
return 'OK' return 'OK'

17
server/template/base.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
<title>Index</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>

View File

@ -0,0 +1,19 @@
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}
</p>
<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 %}

View File

@ -1,15 +1,7 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en">
<head> {% block content %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
<title>Index</title>
</head>
<body>
<h1 style="color: blue">Login Page</h1> <h1 style="color: blue">Login Page</h1>
<!--Google Login--> <!--Google Login-->
@ -41,6 +33,5 @@
<!-- Compiled and minified JavaScript --> <!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
</body>
</html> {% endblock %}

View File

@ -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 %}