2019-09-19 20:49:40 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
2019-09-26 13:00:02 -04:00
|
|
|
Various different tools for Buckler.
|
2019-09-19 20:49:40 -04:00
|
|
|
"""
|
|
|
|
import email.mime.text
|
|
|
|
import smtplib
|
|
|
|
import secrets
|
|
|
|
|
|
|
|
import config
|
|
|
|
|
2019-09-26 13:00:02 -04:00
|
|
|
|
2019-09-19 20:49:40 -04:00
|
|
|
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)
|
2019-09-29 13:25:07 -04:00
|
|
|
invite_url = 'https://' + config.server_domain + str(invite_url)
|
2019-09-19 20:49:40 -04:00
|
|
|
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)
|
2019-09-29 13:25:07 -04:00
|
|
|
confirm_url = 'https://' + config.server_domain + str(confirm_url)
|
2019-09-19 20:49:40 -04:00
|
|
|
body = "Buckle up.\n" + confirm_url
|
2019-09-29 15:28:44 -04:00
|
|
|
send_mail(to_addr, "Confirm Email", body)
|
2019-09-26 13:00:02 -04:00
|
|
|
|
|
|
|
|
|
|
|
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
|
2019-09-26 13:33:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
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
|