|
| 1 | +from src.utils import get_b64encoded_qr_image |
| 2 | +from .forms import LoginForm, RegisterForm, TwoFactorForm |
| 3 | +from src.accounts.models import User |
| 4 | +from src import db, bcrypt |
| 5 | +from flask_login import current_user, login_required, login_user, logout_user |
| 6 | +from flask import Blueprint, flash, redirect, render_template, request, url_for |
| 7 | + |
| 8 | +accounts_bp = Blueprint("accounts", __name__) |
| 9 | + |
| 10 | +HOME_URL = "core.home" |
| 11 | +SETUP_2FA_URL = "accounts.setup_two_factor_auth" |
| 12 | +VERIFY_2FA_URL = "accounts.verify_two_factor_auth" |
| 13 | + |
| 14 | + |
| 15 | +@accounts_bp.route("/register", methods=["GET", "POST"]) |
| 16 | +def register(): |
| 17 | + if current_user.is_authenticated: |
| 18 | + if current_user.is_two_factor_authentication_enabled: |
| 19 | + flash("You are already registered.", "info") |
| 20 | + return redirect(url_for(HOME_URL)) |
| 21 | + else: |
| 22 | + flash( |
| 23 | + "You have not enabled 2-Factor Authentication. Please enable first to login.", "info") |
| 24 | + return redirect(url_for(SETUP_2FA_URL)) |
| 25 | + form = RegisterForm(request.form) |
| 26 | + if form.validate_on_submit(): |
| 27 | + try: |
| 28 | + user = User(username=form.username.data, password=form.password.data) |
| 29 | + db.session.add(user) |
| 30 | + db.session.commit() |
| 31 | + |
| 32 | + login_user(user) |
| 33 | + flash("You are registered. You have to enable 2-Factor Authentication first to login.", "success") |
| 34 | + |
| 35 | + return redirect(url_for(SETUP_2FA_URL)) |
| 36 | + except Exception: |
| 37 | + db.session.rollback() |
| 38 | + flash("Registration failed. Please try again.", "danger") |
| 39 | + |
| 40 | + return render_template("accounts/register.html", form=form) |
| 41 | + |
| 42 | + |
| 43 | +@accounts_bp.route("/login", methods=["GET", "POST"]) |
| 44 | +def login(): |
| 45 | + if current_user.is_authenticated: |
| 46 | + if current_user.is_two_factor_authentication_enabled: |
| 47 | + flash("You are already logged in.", "info") |
| 48 | + return redirect(url_for(HOME_URL)) |
| 49 | + else: |
| 50 | + flash( |
| 51 | + "You have not enabled 2-Factor Authentication. Please enable first to login.", "info") |
| 52 | + return redirect(url_for(SETUP_2FA_URL)) |
| 53 | + |
| 54 | + form = LoginForm(request.form) |
| 55 | + if form.validate_on_submit(): |
| 56 | + user = User.query.filter_by(username=form.username.data).first() |
| 57 | + if user and bcrypt.check_password_hash(user.password, request.form["password"]): |
| 58 | + login_user(user) |
| 59 | + if not current_user.is_two_factor_authentication_enabled: |
| 60 | + flash( |
| 61 | + "You have not enabled 2-Factor Authentication. Please enable first to login.", "info") |
| 62 | + return redirect(url_for(SETUP_2FA_URL)) |
| 63 | + return redirect(url_for(VERIFY_2FA_URL)) |
| 64 | + elif not user: |
| 65 | + flash("You are not registered. Please register.", "danger") |
| 66 | + else: |
| 67 | + flash("Invalid username and/or password.", "danger") |
| 68 | + return render_template("accounts/login.html", form=form) |
| 69 | + |
| 70 | + |
| 71 | +@accounts_bp.route("/logout") |
| 72 | +@login_required |
| 73 | +def logout(): |
| 74 | + logout_user() |
| 75 | + flash("You were logged out.", "success") |
| 76 | + return redirect(url_for("accounts.login")) |
| 77 | + |
| 78 | + |
| 79 | +@accounts_bp.route("/setup-2fa") |
| 80 | +@login_required |
| 81 | +def setup_two_factor_auth(): |
| 82 | + secret = current_user.secret_token |
| 83 | + uri = current_user.get_authentication_setup_uri() |
| 84 | + base64_qr_image = get_b64encoded_qr_image(uri) |
| 85 | + return render_template("accounts/setup-2fa.html", secret=secret, qr_image=base64_qr_image) |
| 86 | + |
| 87 | + |
| 88 | +@accounts_bp.route("/verify-2fa", methods=["GET", "POST"]) |
| 89 | +@login_required |
| 90 | +def verify_two_factor_auth(): |
| 91 | + form = TwoFactorForm(request.form) |
| 92 | + if form.validate_on_submit(): |
| 93 | + if current_user.is_otp_valid(form.otp.data): |
| 94 | + if current_user.is_two_factor_authentication_enabled: |
| 95 | + flash("2FA verification successful. You are logged in!", "success") |
| 96 | + return redirect(url_for(HOME_URL)) |
| 97 | + else: |
| 98 | + try: |
| 99 | + current_user.is_two_factor_authentication_enabled = True |
| 100 | + db.session.commit() |
| 101 | + flash("2FA setup successful. You are logged in!", "success") |
| 102 | + return redirect(url_for(HOME_URL)) |
| 103 | + except Exception: |
| 104 | + db.session.rollback() |
| 105 | + flash("2FA setup failed. Please try again.", "danger") |
| 106 | + return redirect(url_for(VERIFY_2FA_URL)) |
| 107 | + else: |
| 108 | + flash("Invalid OTP. Please try again.", "danger") |
| 109 | + return redirect(url_for(VERIFY_2FA_URL)) |
| 110 | + else: |
| 111 | + if not current_user.is_two_factor_authentication_enabled: |
| 112 | + flash( |
| 113 | + "You have not enabled 2-Factor Authentication. Please enable it first.", "info") |
| 114 | + return render_template("accounts/verify-2fa.html", form=form) |
0 commit comments