Development
This commit is contained in:
parent
f5722f3c7b
commit
d60bf15ce4
15 changed files with 367 additions and 285 deletions
|
|
@ -1,7 +1,7 @@
|
|||
from pathlib import Path
|
||||
from flask import Blueprint, request, session, redirect, flash
|
||||
import json, os, bcrypt, secrets, smtplib
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import os, bcrypt, secrets, smtplib
|
||||
import time
|
||||
from email.message import EmailMessage
|
||||
import auth
|
||||
import config_utils
|
||||
|
|
@ -11,15 +11,7 @@ _PAGE = Path(__file__).parent.name
|
|||
|
||||
bp = Blueprint(_PAGE, __name__)
|
||||
|
||||
CODE_TTL_MIN = 15
|
||||
|
||||
|
||||
def _load_accounts():
|
||||
try:
|
||||
with open(config_utils.ACCOUNTS_FILE) as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
return {'accounts': []}
|
||||
CODE_TTL_SECS = 15 * 60
|
||||
|
||||
|
||||
def _send_verification_email(to_address, code):
|
||||
|
|
@ -38,7 +30,7 @@ def _send_verification_email(to_address, code):
|
|||
msg['To'] = to_address
|
||||
msg.set_content(
|
||||
f'Your verification code is: {code}\n\n'
|
||||
f'This code expires in {CODE_TTL_MIN} minutes.\n\n'
|
||||
f'This code expires in 15 minutes.\n\n'
|
||||
f'If you did not request this, you can ignore this email.'
|
||||
)
|
||||
|
||||
|
|
@ -51,10 +43,19 @@ def _send_verification_email(to_address, code):
|
|||
smtp.send_message(msg)
|
||||
|
||||
|
||||
def _tz_to_offset_seconds(tz_str):
|
||||
try:
|
||||
from zoneinfo import ZoneInfo
|
||||
from datetime import datetime
|
||||
return int(datetime.now(ZoneInfo(tz_str)).utcoffset().total_seconds())
|
||||
except Exception:
|
||||
import settings as _s
|
||||
return _s.get_host_utc_offset()
|
||||
|
||||
|
||||
@bp.route('/action/accountcreate/form_create', methods=['POST'])
|
||||
@auth.require_level('nothing')
|
||||
def form_create():
|
||||
# Abort if already logged in
|
||||
if session.get('access_level', 'nothing') != 'nothing':
|
||||
return redirect('/overview')
|
||||
|
||||
|
|
@ -75,8 +76,7 @@ def form_create():
|
|||
flash('Password must be at least 8 characters.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
accounts = _load_accounts().get('accounts', [])
|
||||
account = next((a for a in accounts if a.get('email_address', '').lower() == email), None)
|
||||
account = config_utils.get_account_by_email(email)
|
||||
|
||||
if account is None:
|
||||
flash('Email address not recognised. Contact your manager.', 'error')
|
||||
|
|
@ -86,10 +86,11 @@ def form_create():
|
|||
flash('This account is already set up. Please log in instead.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
salt = bcrypt.gensalt()
|
||||
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
|
||||
code = f'{secrets.randbelow(1000000):06d}'
|
||||
expires = (datetime.now(tz=timezone.utc) + timedelta(minutes=CODE_TTL_MIN)).isoformat()
|
||||
salt = bcrypt.gensalt()
|
||||
hashed = bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')
|
||||
code = f'{secrets.randbelow(1000000):06d}'
|
||||
expires_ts = int(time.time()) + CODE_TTL_SECS
|
||||
tz_offset = _tz_to_offset_seconds(tz)
|
||||
|
||||
try:
|
||||
_send_verification_email(account['email_address'], code)
|
||||
|
|
@ -97,12 +98,20 @@ def form_create():
|
|||
flash(f'Could not send verification email: {exc}', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
session['pending_create_account'] = {
|
||||
'email': account['email_address'],
|
||||
'hashed_password': hashed.decode('utf-8'),
|
||||
'timezone': tz,
|
||||
'code': code,
|
||||
'expires': expires,
|
||||
}
|
||||
try:
|
||||
con = config_utils.open_accounts_db()
|
||||
con.execute(
|
||||
'''INSERT OR REPLACE INTO pending_verifications
|
||||
(email, hashed_password, tz_offset_seconds, code, expires_ts)
|
||||
VALUES (?,?,?,?,?)''',
|
||||
(account['email_address'].lower(), hashed, tz_offset, code, expires_ts)
|
||||
)
|
||||
con.commit()
|
||||
con.close()
|
||||
except Exception as exc:
|
||||
flash(f'Could not store verification: {exc}', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
session['pending_verify_email'] = account['email_address']
|
||||
|
||||
return redirect('/accountverifyemail')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue