#!/usr/bin/env python3 """ Co-routines for handling various forms in Buckler. """ import tools async def invite_user(request): """Allows an admin to invite a new user.""" if not request['session']['admin']: return {'main': "You do not have permission to do that."} data = await request.post() email = data.get('email') if not email: return {'invite_user': "This field is required."} # TODO: validate email address await tools.send_invite(request, email) return {} async def change_password(request): """Allows a user to change their password.""" errors = {} data = await request.post() current_pw = data.get('current_password') new_pw = data.get('new_password') verify_pw = data.get('verify_password') if not all((current_pw, new_pw, verify_pw)): errors['change_password'] = "All fields are required." return errors if not new_pw == verify_pw: errors['change_password'] = "Passwords do not match." return errors async with request.app['pool'].acquire() as conn: pw_hash = conn.fetchrow( "SELECT password_hash FROM user_info WHERE id = $1", request['session']['id']) if not argon2.verify(current_pw, pw_hash['password_hash']): errors['change_password'] = "Invalid password." return errors h = argon2.hash(new_pw) conn.execute( "UPDATE user_info SET password_hash = $1 WHERE id = $2", h, request['session']['id']) return errors async def delete_key(request): """Allows a user to delete a security key.""" data = await request.post() async with request.app['pool'].acquire() as conn: for key, value in data.items(): key_id = key.replace('fido-', '') if not key_id: continue try: key_id = int(key_id) except ValueError: continue if value != 'on': continue await conn.execute( "DELETE FROM user_credential " "WHERE id = $1 AND user_id = $2", key_id, request['session']['id']) return {} async def delete_session(request): """Allows a user to delete a session .""" data = await request.post() async with request.app['pool'].acquire() as conn: for key, value in data.items(): session_id = key.replace('session-', '', 1) if not session_id: continue if value != 'on': continue await conn.execute( "DELETE FROM user_session " "WHERE id = $1 AND user_id = $2", session_id, request['session']['id']) return {}