Development

This commit is contained in:
Matthew Grotke 2026-05-27 22:04:04 -04:00
parent eed1d295dc
commit d9f3bd8289
45 changed files with 635 additions and 666 deletions

View file

@ -1,3 +1,4 @@
from pathlib import Path
from flask import Blueprint, request, session, redirect, flash
import json, os, bcrypt, secrets, smtplib
from datetime import datetime, timezone, timedelta
@ -6,7 +7,9 @@ from auth import require_level
from config_utils import WEB_APP_DISPLAY_NAME, ACCOUNTS_FILE
import sanitize
bp = Blueprint('accountcreate', __name__)
_PAGE = Path(__file__).parent.name
bp = Blueprint(_PAGE, __name__)
CODE_TTL_MIN = 15
@ -48,12 +51,12 @@ def _send_verification_email(to_address, code):
smtp.send_message(msg)
@bp.route('/action/create_account', methods=['POST'])
@bp.route('/action/accountcreate/form_create', methods=['POST'])
@require_level('nothing')
def create_account():
def form_create():
# Abort if already logged in
if session.get('access_level', 'nothing') != 'nothing':
return redirect('/view/view_overview')
return redirect('/overview')
email = sanitize.email(request.form.get('email', ''))
password = request.form.get('password', '')
@ -62,26 +65,26 @@ def create_account():
if not email or not password or not password_confirm or not tz:
flash('All fields are required.', 'error')
return redirect('/view/view_createaccount')
return redirect(f'/{_PAGE}')
if password != password_confirm:
flash('Passwords do not match.', 'error')
return redirect('/view/view_createaccount')
return redirect(f'/{_PAGE}')
if len(password) < 8:
flash('Password must be at least 8 characters.', 'error')
return redirect('/view/view_createaccount')
return redirect(f'/{_PAGE}')
accounts = _load_accounts().get('accounts', [])
account = next((a for a in accounts if a.get('email_address', '').lower() == email), None)
if account is None:
flash('Email address not recognised. Contact your manager.', 'error')
return redirect('/view/view_createaccount')
return redirect(f'/{_PAGE}')
if account.get('hashed_password'):
flash('This account is already set up. Please log in instead.', 'error')
return redirect('/view/view_createaccount')
return redirect(f'/{_PAGE}')
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
@ -92,7 +95,7 @@ def create_account():
_send_verification_email(account['email_address'], code)
except Exception as exc:
flash(f'Could not send verification email: {exc}', 'error')
return redirect('/view/view_createaccount')
return redirect(f'/{_PAGE}')
session['pending_create_account'] = {
'email': account['email_address'],
@ -102,4 +105,4 @@ def create_account():
'expires': expires,
}
return redirect('/view/view_verifyemail')
return redirect('/accountverifyemail')

View file

@ -1,5 +1,4 @@
{
"id": "view_createaccount",
"client_requirement": "client_is_nothing=",
"items": [
{
@ -22,7 +21,7 @@
},
{
"type": "form",
"action": "/action/create_account",
"action": "/action/accountcreate/form_create",
"method": "post",
"items": [
{
@ -58,7 +57,7 @@
},
{
"type": "button_primary",
"action": "/action/create_account",
"action": "/action/accountcreate/form_create",
"method": "post",
"text": "Create Account",
"class": "btn-full"
@ -69,7 +68,7 @@
"type": "p",
"text": "Already have an account?",
"link": {
"action": "/view/view_login",
"action": "/accountlogin",
"text": "Log In"
}
}
@ -94,7 +93,7 @@
},
{
"type": "button_primary",
"action": "/view/overview",
"action": "/overview",
"text": "Go to Overview"
}
]