Reworked login and register

This commit is contained in:
Emily 2019-05-12 18:31:26 +01:00
parent 3a1137561d
commit 81dbaceb46
5 changed files with 195 additions and 98 deletions

View File

@ -5,6 +5,10 @@ from flask_login import UserMixin
from objects import glob from objects import glob
FORM_RENDER_KW = {
"class_": "form-control"
}
class BillForm(Form): class BillForm(Form):
payment_to = StringField("Payment to", [validators.DataRequired()]) payment_to = StringField("Payment to", [validators.DataRequired()])
description = TextAreaField("Description", render_kw = { description = TextAreaField("Description", render_kw = {
@ -19,35 +23,41 @@ class LoginForm(Form):
email = StringField("Email", [ email = StringField("Email", [
validators.DataRequired(), validators.DataRequired(),
validators.Length(min=6, max=254) validators.Length(min=6, max=254)
]) ],
render_kw = FORM_RENDER_KW)
password = PasswordField("Password", [ password = PasswordField("Password", [
validators.DataRequired(), validators.DataRequired(),
validators.Length(min=4, max=127) validators.Length(min=4, max=127)
]) ],
render_kw = FORM_RENDER_KW)
class RegisterForm(Form): class RegisterForm(Form):
email = StringField("Email", [ email = StringField("Email", [
validators.DataRequired(), validators.DataRequired(),
validators.Length(min=6, max=254) validators.Length(min=6, max=254)
]) ],
render_kw = FORM_RENDER_KW)
password = PasswordField("Password", [ password = PasswordField("Password", [
validators.DataRequired(), validators.DataRequired(),
validators.Length(min=4, max=127), validators.Length(min=4, max=127),
validators.EqualTo("confirm_password", message = "Passwords must match") validators.EqualTo("confirm_password", message = "Passwords must match")
]) ],
confirm_password = PasswordField("Repeat Password") render_kw = FORM_RENDER_KW)
confirm_password = PasswordField("Repeat Password", render_kw = FORM_RENDER_KW)
firstname = StringField("Firstname", [ firstname = StringField("Firstname", [
validators.DataRequired(), validators.DataRequired(),
validators.Length(min=2, max=30) validators.Length(min=2, max=30)
]) ],
render_kw = FORM_RENDER_KW)
surname = StringField("Surname", [ surname = StringField("Surname", [
validators.DataRequired(), validators.DataRequired(),
validators.Length(min=2, max=30) validators.Length(min=2, max=30)
]) ],
render_kw = FORM_RENDER_KW)
accept_tos = BooleanField("I accept the TOS", [validators.DataRequired()]) accept_tos = BooleanField("I accept the TOS", [validators.DataRequired()])

View File

@ -70,20 +70,31 @@ def login():
flash(gettext("Already logged in"), "info") flash(gettext("Already logged in"), "info")
return redirect(url_for("dashboard")) return redirect(url_for("dashboard"))
form = LoginForm(request.form) form_login = LoginForm(request.form)
if request.method == "POST" and form.validate(): form_register = RegisterForm(request.form)
if request.method == "POST":
if form_register.validate():
try: try:
user = User((form.email.data, form.password.data)) register_account(form_register.email.data, form_register.password.data, form_register.firstname.data, form_register.surname.data)
flash(gettext("User registered"), "success")
except Exception as e: except Exception as e:
flash(gettext(str(e)), "danger") flash(gettext(str(e)), "danger")
return render_template("login.html", form=form) return redirect(url_for("login"))
elif form_login.validate():
try:
user = User((form_login.email.data, form_login.password.data))
flask_login.login_user(user) flask_login.login_user(user)
logged_in_users.append(user) logged_in_users.append(user)
flash(gettext("Logged in"), "success") flash(gettext("Logged in"), "success")
return redirect(url_for("dashboard")) except Exception as e:
return render_template("login.html", form=form) flash(gettext(str(e)), "danger")
return redirect(url_for("login"))
return redirect(url_for("dashboard")) # Valid login > Redirect to dashboard as user is logged in
return render_template("login.html", form = {
"login": form_login,
"register": form_register
})
@glob.app.route("/register", methods = ["GET", "POST"]) @glob.app.route("/register", methods = ["GET", "POST"])
def register(): def register():

BIN
static/img/login-bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

View File

@ -3,57 +3,137 @@
{% extends "layout/bootstrap.html" %} {% extends "layout/bootstrap.html" %}
{% block content %} {% block content %}
<script src="{{ url_for('static', filename='js/alerts.js') }}"></script> <style>
<div class="container pt-3"> html, body {
<div class="row alert-section"> height: 100%;
<div class="col-md-8 mx-auto"> }
<div class="card rounded-1">
<div class="card-header navbar topnav"> .main-head{
<h3 class="mb-0">Login Methods</h3> height: 150px;
<div class="my-2 my-lg-0 d-flex"> background: #FFF;
<a href="{{ url_for('register') }}">Register</a> }
.sidenav {
height: 100%;
background-color: #000;
overflow-x: hidden;
padding-top: 20px;
}
.main {
padding: 0px 10px;
display: grid;
grid-template-rows: 25% auto;
grid-row-gap: 8px;
height: 100%;
}
.main > .col:nth-child(1n) {
grid-row-start: 1;
}
.main > .col:nth-child(2n) {
grid-row-start: 2;
}
@media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
}
@media screen and (max-width: 450px) {
.login-form{
margin-top: 10%;
}
.register-form{
margin-top: 10%;
}
}
@media screen and (min-width: 768px){
.main{
margin-left: 40%;
}
.sidenav{
width: 40%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
}
}
.login-main-text{
margin-top: 20%;
padding: 60px;
color: #fff;
}
.login-main-text h2{
font-weight: 300;
}
.btn-black{
background-color: #000 !important;
color: #fff;
}
.hidable[aria-expanded="true"] {
display: none;
}
.toggle-form > form:nth-child(2n) {
display: none;
}
.toggle-form.toggled > form:nth-child(1n) {
display: none;
}
.toggle-form.toggled > form:nth-child(2n) {
display: block;
}
</style>
<script>
function toggleform(caller) {
let selectedDOM = caller;
do {
if (selectedDOM.classList.contains("toggle-form")){
let classes = selectedDOM.classList;
classes[classes.contains("toggled") ? "remove" : "add"]("toggled");
return;
}
selectedDOM = selectedDOM.parentElement;
} while (selectedDOM != null);
throw Error("Missing toggle-form class for self/parent(s)");
}
</script>
<div class="sidenav">
<div class="login-main-text">
<h2>Husstanden<br>Login Page</h2>
<p>Login is required to use this service.</p>
</div> </div>
</div>
<div class="main">
<div class="col pt-4">
{% with messages = get_flashed_messages(with_categories = true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} fade in show" role="alert" style="margin-bottom:0px;padding:6px;">
<a href="#" class="close" data-dismiss="alert" aria-label="close" style="margin-left:10px;">&times;</a>
{{ message }}
</div> </div>
<div class="card-body row"> {% endfor %}
<div class="col-md-6"> {% endif %}
<h5>Electronic ID</h5> {% endwith %}
<p class="lead">
Secure login using Electronic ID allows Husstanden to show you banking details, bills and receipts.<br>
<a target="_blank" href="https://eid.difi.no/en/id-porten/how-obtain-electronic-id">How to obtain an Electronic ID</a>
</p>
</div> </div>
<div class="col-md-6"> <div class="col col-md-6 col-sm-12">
<h5>House Account</h5> <div class="login-form">
<p class="lead">
Accounts with less privileges and fast login to view non-sensitive information.<br>
Multiple house accounts can be created by logging in with house holder's verified <i>Electronic ID</i>.
</p>
</div>
</div>
<hr>
<div class="card-body row pt-2">
<div class="col-md-6 pb-2">
<a class="btn btn-primary btn-lg btn-block" href="#TODO_LOGIN_EID" onclick="alertAbove(this, 'warning', 'This should redirect the user to Electronic ID page (but due to phishing, we can not demo this)')">Electronic ID</a>
</div>
<div class="col-md-6">
<a class="btn btn-primary btn-lg btn-block" href="#" data-toggle="modal" data-target="#myModal">House Account</a>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Login</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<div class="modal-body">
{% macro render_field(field) %} {% macro render_field(field) %}
<dt>{{ field.label }} <div class="form-group">
<dd>{{ field(**kwargs)|safe }} {{ field.label }}
{{ field(**kwargs)|safe }}
{% if field.errors %} {% if field.errors %}
<ul class=errors> <ul class=errors>
{% for error in field.errors %} {% for error in field.errors %}
@ -61,31 +141,27 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
</dd> </div>
{% endmacro %} {% endmacro %}
<form method=post> <div class="toggle-form false">
<dl> <form method="post">
{{ render_field(form.email) }} {{ render_field(form.login.email) }}
{{ render_field(form.password) }} {{ render_field(form.login.password) }}
</dl> <button class="btn btn-black">Login</button>
<input type=submit value="Login"> <span class="btn btn-secondary" onclick="toggleform(this)">Register</span>
</form>
<form method="post">
{{ render_field(form.register.email) }}
{{ render_field(form.register.password) }}
{{ render_field(form.register.confirm_password) }}
{{ render_field(form.register.firstname) }}
{{ render_field(form.register.surname) }}
{{ render_field(form.register.accept_tos) }}
<span class="btn btn-secondary" onclick="toggleform(this)">Login</span>
<button class="btn btn-black">Register</button>
</form> </form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script>
{% with messages = get_flashed_messages() %}
{% if messages %}
let alertArea = document.getElementsByClassName("alert-section")[0];
{% for message in messages %}
alertAbove(alertArea, "info", "{{ message }}");
{% endfor %}
{% endif %}
{% endwith %}
</script>
{% endblock %} {% endblock %}

View File

@ -18,7 +18,7 @@
<!-- Modal content--> <!-- Modal content-->
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title">Add bill</h4> <h4 class="modal-title">{{ _("Add bill") }}</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button> <button type="button" class="close" data-dismiss="modal">&times;</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">