from pathlib import Path from flask import Blueprint, request, session, redirect, flash import time, secrets import auth import config_utils _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') from pages.accountcreate.action import CODE_TTL_SECS token = session.sid try: con = config_utils.open_accounts_db() client = con.execute( 'SELECT * FROM clients WHERE cookie_unique_token=?', (token,) ).fetchone() con.close() except Exception: client = None if not client or not client['email']: flash('No pending account creation found. Please start over.', 'error') return redirect('/accountcreate') if int(time.time()) > client['code_sent_ts'] + CODE_TTL_SECS: try: con = config_utils.open_accounts_db() con.execute( '''UPDATE clients SET email=NULL, hashed_password=NULL, tz_offset_seconds=NULL, verification_code=NULL, code_sent_ts=NULL WHERE cookie_unique_token=?''', (token,) ) con.commit() con.close() except Exception: pass flash('Verification code has expired. Please start over.', 'error') return redirect('/accountcreate') submitted = request.form.get('code', '').strip() if submitted != client['verification_code']: flash('Incorrect verification code.', 'error') return redirect(f'/{_PAGE}') pending_email = client['email'] account = config_utils.get_account_by_email(pending_email) if account is None: flash('Account no longer exists. Contact your manager.', 'error') return redirect('/accountcreate') if account.get('hashed_password'): 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=?', (client['hashed_password'], now, 'self', account['account_id']) ) con.execute( '''UPDATE clients SET email=NULL, hashed_password=NULL, tz_offset_seconds=NULL, verification_code=NULL, code_sent_ts=NULL WHERE cookie_unique_token=?''', (token,) ) con.commit() con.close() except Exception as exc: flash(f'Could not complete account setup: {exc}', 'error') return redirect(f'/{_PAGE}') session['account_id'] = account['account_id'] session['tz_offset_seconds'] = int(client['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 token = session.sid try: con = config_utils.open_accounts_db() client = con.execute( 'SELECT * FROM clients WHERE cookie_unique_token=?', (token,) ).fetchone() con.close() except Exception: client = None if not client or not client['email']: flash('No pending account creation found. Please start over.', 'error') return redirect('/accountcreate') code = f'{secrets.randbelow(1000000):06d}' code_sent_ts = int(time.time()) try: _send_verification_email(client['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 clients SET verification_code=?, code_sent_ts=? WHERE cookie_unique_token=?', (code, code_sent_ts, token) ) con.commit() con.close() except Exception: pass flash('A new verification code has been sent.', 'success') return redirect(f'/{_PAGE}')