from pathlib import Path from flask import Blueprint, request, session, redirect, flash import json, bcrypt import auth import config_utils import sanitize _PAGE = Path(__file__).parent.name bp = Blueprint(_PAGE, __name__) def _load_accounts(): try: with open(config_utils.ACCOUNTS_FILE) as f: return json.load(f) except Exception: return {'accounts': []} def _save_accounts(data): with open(config_utils.ACCOUNTS_FILE, 'w') as f: json.dump(data, f, indent=2) @bp.route('/action/preferences/accountdetails_save', methods=['POST']) @auth.require_level('viewer') def accountdetails_save(): tz = sanitize.timezone(request.form.get('timezone', '').strip()) if not tz: flash('Timezone is required.', 'error') return redirect(f'/{_PAGE}') email = session.get('email_address', '').lower() data = _load_accounts() accounts = data.get('accounts', []) account = next((a for a in accounts if a.get('email_address', '').lower() == email), None) if account is None: flash('Account not found. Please log in again.', 'error') return redirect('/accountlogin') account['timezone'] = tz _save_accounts(data) session['timezone'] = tz flash('Preferences saved.', 'success') return redirect(f'/{_PAGE}') @bp.route('/action/preferences/changepassword_save', methods=['POST']) @auth.require_level('viewer') def changepassword_save(): current_password = request.form.get('current_password', '') new_password = request.form.get('new_password', '') confirm_password = request.form.get('confirm_password', '') if not current_password or not new_password or not confirm_password: flash('All fields are required.', 'error') return redirect(f'/{_PAGE}') if new_password != confirm_password: flash('New passwords do not match.', 'error') return redirect(f'/{_PAGE}') if len(new_password) < 8: flash('New password must be at least 8 characters.', 'error') return redirect(f'/{_PAGE}') email = session.get('email_address', '').lower() data = _load_accounts() accounts = data.get('accounts', []) account = next((a for a in accounts if a.get('email_address', '').lower() == email), None) if account is None: flash('Account not found. Please log in again.', 'error') return redirect('/accountlogin') stored_hash = account.get('hashed_password', '').encode('utf-8') if not bcrypt.checkpw(current_password.encode('utf-8'), stored_hash): flash('Current password is incorrect.', 'error') return redirect(f'/{_PAGE}') salt = bcrypt.gensalt() hashed = bcrypt.hashpw(new_password.encode('utf-8'), salt) account['hashed_password'] = hashed.decode('utf-8') account['salt'] = salt.decode('utf-8') _save_accounts(data) flash('Password changed successfully.', 'success') return redirect(f'/{_PAGE}')