from pathlib import Path from flask import Blueprint, request, session, redirect, flash import time, secrets import auth import config_utils import settings _PAGE = Path(__file__).parent.name bp = Blueprint(_PAGE, __name__) @bp.route('/action/accountverifyemail/email_verify', methods=['POST']) @auth.require_level('nothing') def email_verify(): if session.get('access_level', 'nothing') != 'nothing': return redirect('/overview') pending_email = session.get('pending_verify_email', '').lower() if not pending_email: flash('No pending account creation found. Please start over.', 'error') return redirect('/accountcreate') try: con = config_utils.open_accounts_db() row = con.execute( 'SELECT * FROM pending_verifications WHERE email=?', (pending_email,) ).fetchone() con.close() except Exception: row = None if not row: flash('No pending account creation found. Please start over.', 'error') return redirect('/accountcreate') if int(time.time()) > row['expires_ts']: try: con = config_utils.open_accounts_db() con.execute('DELETE FROM pending_verifications WHERE email=?', (pending_email,)) con.commit() con.close() except Exception: pass session.pop('pending_verify_email', None) flash('Verification code has expired. Please start over.', 'error') return redirect('/accountcreate') submitted = request.form.get('code', '').strip() if submitted != row['code']: flash('Incorrect verification code.', 'error') return redirect(f'/{_PAGE}') account = config_utils.get_account_by_email(pending_email) if account is None: session.pop('pending_verify_email', None) flash('Account no longer exists. Contact your manager.', 'error') return redirect('/accountcreate') if account.get('hashed_password'): session.pop('pending_verify_email', None) flash('This account is already set up. Please log in.', 'error') return redirect('/accountlogin') now = int(time.time()) try: con = config_utils.open_accounts_db() con.execute( 'UPDATE accounts SET hashed_password=?, created_ts=?, created_by=? WHERE account_id=?', (row['hashed_password'], now, 'self', account['account_id']) ) con.execute('DELETE FROM pending_verifications WHERE email=?', (pending_email,)) con.commit() con.close() except Exception as exc: flash(f'Could not complete account setup: {exc}', 'error') return redirect(f'/{_PAGE}') session.pop('pending_verify_email', None) session['account_id'] = account['account_id'] session['tz_offset_seconds'] = int(row['tz_offset_seconds']) session['apply_changes_immediately'] = False session.permanent = True return redirect('/overview') @bp.route('/action/accountverifyemail/email_resend') @auth.require_level('nothing') def email_resend(): if session.get('access_level', 'nothing') != 'nothing': return redirect('/overview') from pages.accountcreate.action import _send_verification_email, CODE_TTL_SECS pending_email = session.get('pending_verify_email', '').lower() if not pending_email: flash('No pending account creation found. Please start over.', 'error') return redirect('/accountcreate') code = f'{secrets.randbelow(1000000):06d}' expires_ts = int(time.time()) + CODE_TTL_SECS try: _send_verification_email(pending_email, code) except Exception as exc: flash(f'Could not resend verification email: {exc}', 'error') return redirect(f'/{_PAGE}') try: con = config_utils.open_accounts_db() con.execute( 'UPDATE pending_verifications SET code=?, expires_ts=? WHERE email=?', (code, expires_ts, pending_email) ) con.commit() con.close() except Exception: pass flash('A new verification code has been sent.', 'success') return redirect(f'/{_PAGE}')