from pathlib import Path from flask import Blueprint, request, session, redirect, flash import bcrypt import auth import config_utils import sanitize import settings _PAGE = Path(__file__).parent.name bp = Blueprint(_PAGE, __name__) @bp.route('/action/accountlogin/form_login', methods=['POST']) @auth.require_level('nothing') def form_login(): if session.get('access_level', 'nothing') != 'nothing': return redirect('/overview') email = sanitize.email(request.form.get('email', '')) password = request.form.get('password', '') if not email or not password: flash('Email address and password are required.', 'error') return redirect(f'/{_PAGE}') account = config_utils.get_account_by_email(email) if account is None: flash('Email address not recognised.', 'error') return redirect(f'/{_PAGE}') if not account.get('hashed_password'): # Either brand-new account or email change approved - check for a pending verification row try: con = config_utils.open_accounts_db() client = con.execute( 'SELECT * FROM clients WHERE email=? AND verification_code IS NOT NULL', (email,) ).fetchone() if client and client['cookie_unique_token'] != session.sid: con.execute( '''INSERT INTO clients (cookie_unique_token, email, hashed_password, verification_code, code_sent_ts) VALUES (?,?,?,?,?) ON CONFLICT(cookie_unique_token) DO UPDATE SET email=excluded.email, hashed_password=excluded.hashed_password, verification_code=excluded.verification_code, code_sent_ts=excluded.code_sent_ts''', (session.sid, client['email'], client['hashed_password'], client['verification_code'], client['code_sent_ts']) ) con.execute('DELETE FROM clients WHERE cookie_unique_token=?', (client['cookie_unique_token'],)) con.commit() con.close() except Exception: client = None if client: flash('Please check your inbox and enter your verification code.', 'info') return redirect('/accountverifyemail') flash('Account setup is not complete. Please use Create Account to set your password first.', 'error') return redirect(f'/{_PAGE}') if not bcrypt.checkpw(password.encode('utf-8'), account['hashed_password'].encode('utf-8')): flash('Invalid email address or password.', 'error') return redirect(f'/{_PAGE}') session.clear() session['account_id'] = account['account_id'] session['tz_offset_seconds'] = settings.get_host_utc_offset() session['timezone'] = settings.get_host_timezone() session['apply_changes_immediately'] = False session.permanent = True return redirect('/overview')