#!/usr/bin/env python3 """ Various different tools for Buckler. """ import email.mime.text import smtplib import secrets import config def send_mail(to_addr, subject, body): """ Sends an email. """ msg = email.mime.text.MIMEText(body, 'plain', 'utf8') msg['From'] = config.email['user'] msg['To'] = to_addr msg['Subject'] = subject with smtplib.SMTP_SSL(config.email['host'],config.email['port']) as server: server.login(config.email['user'], config.email['password']) server.send_message(msg) async def send_invite(request, to_addr): """ Sends an invitation. """ token = secrets.token_urlsafe(32) async with request.app['pool'].acquire() as conn: await conn.execute( "INSERT INTO invite (email, token) " "VALUES ($1, $2)", to_addr, token) d = {'invite': token} invite_url = request.app.router['register'].url_for().with_query(d) invite_url = 'https://' + config.server_domain + str(invite_url) body = "Buckle up.\n" + invite_url send_mail(to_addr, "Buckler Invite", body) async def send_confirmation(request, user_id, to_addr): """ Sends an email confirmation. """ token = secrets.token_urlsafe(32) async with request.app['pool'].acquire() as conn: await conn.execute( "INSERT INTO email_confirmation (user_id, token) " "VALUES ($1, $2)", user_id, token) d = {'confirm': token} confirm_url = request.app.router['register'].url_for().with_query(d) confirm_url = 'https://' + config.server_domain + str(confirm_url) body = "Buckle up.\n" + confirm_url send_mail(to_addr, "Confirm Email", body) async def validate_register(request, form): """Validate data from the registration form.""" username = form.get('username') email = form.get('email') password = form.get('password') password_verify = form.get('password_verify') async with request.app['pool'].acquire() as conn: users = await conn.fetch( "SELECT username, email FROM user_info " "WHERE username = $1 OR email = $2", username, email) errors = {'password': [], 'username': [], 'email': []} if password != password_verify: errors['password'].append("Passwords do not match.") if len(password) < 8 or len(password) > 10240: errors['password'].append( "Password must be between 8 and 10240 characters long.") if len(username) < 3 or len(username) > 20: errors['username'].append( "Username must be between 3 and 20 characters long.") if username in [user['username'] for user in users]: errors['username'].append("Username already in use.") if email in [user['email'] for user in users]: errors['email'].append("Email already in use.") return errors def find_dict(lst, key, value): """ Returns the index of the dictionary in the given `lst` which has d[`key`] == `value`. """ for i, d in enumerate(lst): if d[key] == value: return i return -1