add confirmation via unique link
This commit is contained in:
47
auth.py
47
auth.py
@@ -1,4 +1,6 @@
|
||||
from datetime import datetime
|
||||
import functools
|
||||
import logging
|
||||
from django import db
|
||||
|
||||
from flask import (
|
||||
@@ -8,8 +10,8 @@ from werkzeug.security import check_password_hash, generate_password_hash
|
||||
from itsdangerous import URLSafeTimedSerializer
|
||||
|
||||
from db import get_db
|
||||
from app import app
|
||||
|
||||
import app
|
||||
import calendar_interface
|
||||
|
||||
bp = Blueprint('auth', __name__, url_prefix='/auth')
|
||||
|
||||
@@ -29,6 +31,7 @@ def register():
|
||||
error = 'Password is required.'
|
||||
elif not email:
|
||||
error = 'Email is required.'
|
||||
# TODO: check passwrd complexity
|
||||
|
||||
if error is None:
|
||||
try:
|
||||
@@ -37,10 +40,19 @@ def register():
|
||||
(username, email, generate_password_hash(password)),
|
||||
)
|
||||
db.commit()
|
||||
|
||||
except db.IntegrityError:
|
||||
error = f"User mit email {email} existiert bereits."
|
||||
else:
|
||||
return redirect(url_for("auth.login"))
|
||||
token = generate_confirmation_token(email)
|
||||
confirm_url = url_for('auth.confirm_email', token=token, _external=True)
|
||||
logging.info("Generated confirmation url: %s", confirm_url)
|
||||
content = render_template('auth/confirm_mail.html', confirm_url=confirm_url, username=username, email=email)
|
||||
subject = "Registrierung für Planner von %s" % email
|
||||
calendar_interface.send_mail("struebin.patrick@gmail.com", subject, content)
|
||||
|
||||
flash("Registrierung erfolgreich.")
|
||||
return redirect(url_for("index"))
|
||||
|
||||
flash(error)
|
||||
|
||||
@@ -96,6 +108,7 @@ def login_required(view): # use this as decorator
|
||||
@functools.wraps(view)
|
||||
def wrapped_view(**kwargs):
|
||||
if g.user is None:
|
||||
flash("Benutzer bitte anmelden.")
|
||||
return redirect(url_for('auth.login'))
|
||||
elif not g.user["confirmed"]:
|
||||
flash("Benutzer noch nicht freigeschaltet.")
|
||||
@@ -107,17 +120,17 @@ def login_required(view): # use this as decorator
|
||||
|
||||
|
||||
def generate_confirmation_token(email):
|
||||
serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
|
||||
return serializer.dumps(email, salt=app.config['SECURITY_PASSWORD_SALT'])
|
||||
serializer = URLSafeTimedSerializer(app.app.config['SECRET_KEY'])
|
||||
return serializer.dumps(email, salt=app.app.config['SECURITY_PASSWORD_SALT'])
|
||||
|
||||
|
||||
def confirm_token(token, expiration=3600):
|
||||
serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
|
||||
def confirm_token(token, expiration=3600*14*28): # 2 Wochen expiration
|
||||
serializer = URLSafeTimedSerializer(app.app.config['SECRET_KEY'])
|
||||
try:
|
||||
email = serializer.loads(
|
||||
token,
|
||||
salt=app.config['SECURITY_PASSWORD_SALT'],
|
||||
# max_age=expiration
|
||||
salt=app.app.config['SECURITY_PASSWORD_SALT'],
|
||||
max_age=expiration
|
||||
)
|
||||
except:
|
||||
return False
|
||||
@@ -125,22 +138,22 @@ def confirm_token(token, expiration=3600):
|
||||
|
||||
|
||||
@bp.route('/confirm/<token>')
|
||||
@login_required
|
||||
# @login_required # TODO: notwendig? security ?
|
||||
def confirm_email(token):
|
||||
try:
|
||||
email = confirm_token(token)
|
||||
except:
|
||||
flash('The confirmation link is invalid or has expired.', 'danger')
|
||||
|
||||
outcome = 'The confirmation link is invalid or has expired.'
|
||||
if g.user["confirmed"]:
|
||||
flash('Account already confirmed. Please login.', 'success')
|
||||
outcome = 'Account already confirmed.'
|
||||
|
||||
else:
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"UPDATE user SET confirmed = '1' where email = ?",
|
||||
(email,)
|
||||
"UPDATE user SET confirmed = '1', confirmation_date = ? where email = ?",
|
||||
(str(datetime.now()), email)
|
||||
)
|
||||
db.commit()
|
||||
outcome= "User wurde erfolgreich freigeschaltet."
|
||||
|
||||
flash('You have confirmed your account. Thanks!', 'success')
|
||||
return redirect(url_for('main.home'))
|
||||
return render_template('auth/confirmation_successful.html', email=email, outcome=outcome)
|
||||
@@ -85,10 +85,7 @@ def execute_patch_request(token, endpoint, data):
|
||||
def send_mail(to, subject, content, user_id=USER_ID):
|
||||
|
||||
token=get_access_token()
|
||||
|
||||
with open("templates/auth/activate.html") as f:
|
||||
content=f.read()
|
||||
|
||||
|
||||
mail = {
|
||||
"message": {
|
||||
"subject": subject,
|
||||
|
||||
@@ -5,5 +5,6 @@ CREATE TABLE user (
|
||||
username TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
confirmed BOOLEAN DEFAULT FALSE
|
||||
confirmed BOOLEAN DEFAULT FALSE,
|
||||
confirmation_date TEXT
|
||||
);
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<p>Welcome! Thanks for signing up. Please follow this link to activate your account:</p>
|
||||
<p><a href="{{ confirm_url }}">{{ confirm_url }}</a></p>
|
||||
<br>
|
||||
<p>Cheers!</p>
|
||||
6
templates/auth/confirm_mail.html
Normal file
6
templates/auth/confirm_mail.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<p>{{username}} with email {{email}} wants to be confirmed.</p>
|
||||
<p>follow this link only if the user can be trusted to activate the account:</p>
|
||||
<p><a href="{{ confirm_url }}"> {{ confirm_url }}
|
||||
</a></p>
|
||||
<br>
|
||||
<p>Cheers!</p>
|
||||
7
templates/auth/confirmation.html
Normal file
7
templates/auth/confirmation.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% block title %}Benutzer mit email: {{email}}.{% endblock %}</h1>
|
||||
<h1>{% block title %}{{outcome}}.{% endblock %}</h1>
|
||||
|
||||
{% endblock %}
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
<label for="email">Email (Account login)</label>
|
||||
<input type="email" name="email" id="email" required>
|
||||
<label for="username">Name</label>
|
||||
<input name="username" id="username" required>
|
||||
<label for="email">Email</label>
|
||||
<input type="email" name="email" id="email" required>
|
||||
<label for="password">Password</label>
|
||||
<input type="password" name="password" id="password" required>
|
||||
<input type="submit" value="Register">
|
||||
|
||||
Reference in New Issue
Block a user