Development

This commit is contained in:
Matthew Grotke 2026-06-12 11:16:31 -04:00
parent c561f2f548
commit 1beb660be1
8 changed files with 280 additions and 48 deletions

View file

@ -1,6 +1,6 @@
from pathlib import Path
from flask import Blueprint, request, session, redirect, flash
import os, re, sqlite3
import os, re, secrets, sqlite3, time
from datetime import datetime, timezone
import auth
import config_utils
@ -13,6 +13,93 @@ bp = Blueprint(_PAGE, __name__)
VALID_LEVELS = {'viewer': 1, 'administrator': 2, 'manager': 3}
@bp.route('/action/accountmanage/email_change_deny', methods=['POST'])
@auth.require_level('manager')
def email_change_deny():
account_id = request.form.get('account_id', '').strip()
if not account_id:
flash('Invalid request.', 'error')
return redirect(f'/{_PAGE}')
try:
con = config_utils.open_accounts_db()
con.execute('UPDATE accounts SET requested_email=NULL WHERE account_id=?', (account_id,))
con.commit()
con.close()
flash('Email change request denied.', 'success')
except Exception as exc:
flash(f'Could not deny request: {exc}', 'error')
return redirect(f'/{_PAGE}')
@bp.route('/action/accountmanage/email_change_approve', methods=['POST'])
@auth.require_level('manager')
def email_change_approve():
from pages.accountcreate.action import _send_verification_email, CODE_TTL_SECS
account_id = request.form.get('account_id', '').strip()
if not account_id:
flash('Invalid request.', 'error')
return redirect(f'/{_PAGE}')
try:
con = config_utils.open_accounts_db()
row = con.execute(
'SELECT * FROM accounts WHERE account_id=?', (account_id,)
).fetchone()
con.close()
except Exception:
row = None
if not row or not row['requested_email']:
flash('No pending email change found.', 'error')
return redirect(f'/{_PAGE}')
new_email = row['requested_email']
old_password = row['hashed_password']
code = f'{secrets.randbelow(1000000):06d}'
code_sent_ts = int(time.time())
try:
_send_verification_email(new_email, code)
except Exception as exc:
flash(f'Could not send verification email: {exc}', 'error')
return redirect(f'/{_PAGE}')
try:
con = config_utils.open_accounts_db()
last_cookie = con.execute(
'SELECT session_id FROM sessions WHERE account_id=? ORDER BY last_seen_ts DESC LIMIT 1',
(account_id,)
).fetchone()
cookie = last_cookie['session_id'] if last_cookie else None
if cookie:
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''',
(cookie, new_email, old_password, code, code_sent_ts)
)
con.execute(
'UPDATE accounts SET email=?, hashed_password=NULL, requested_email=NULL WHERE account_id=?',
(new_email, account_id)
)
con.execute('DELETE FROM sessions WHERE account_id=?', (account_id,))
con.commit()
con.close()
except Exception as exc:
flash(f'Could not apply email change: {exc}', 'error')
return redirect(f'/{_PAGE}')
flash(f'Email changed to {new_email}. A verification email has been sent.', 'success')
return redirect(f'/{_PAGE}')
@bp.route('/action/accountmanage/session_invalidate', methods=['POST'])
@auth.require_level('manager')
def session_invalidate():