diff --git a/config.py.template b/config.py.template
index e305868..73d7e76 100644
--- a/config.py.template
+++ b/config.py.template
@@ -21,3 +21,5 @@ mailserver_db = {
'host': 'localhost',
'port': 5432,
}
+max_password = 1024
+min_password = 8
diff --git a/forms.py b/forms.py
new file mode 100644
index 0000000..195e3ea
--- /dev/null
+++ b/forms.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+"""
+Validates and handles forms.
+"""
+from passlib.hash import argon2
+
+import config
+
+async def change_password(request, user_data):
+ """Changes the email account password."""
+ user_id = int(request.cookies.get('userid'))
+ data = await request.post()
+
+ current_password = data.get('current_password', '')
+ new_password = data.get('new_password', '')
+ verify_new_password = data.get('verify_new_password', '')
+
+ if not argon2.verify(current_password, user_data['password']):
+ result = {
+ 'ok': False,
+ 'message': "Current password does not match."
+ }
+ return result
+
+ if new_password != verify_new_password:
+ result = {
+ 'ok': False,
+ 'message': "New passwords do not match."
+ }
+ return result
+
+ if len(new_password) > config.max_password:
+ result = {
+ 'ok': False,
+ 'message': "Maximum password length is 1024 characters."
+ }
+ return result
+
+ if len(new_password) < config.min_password:
+ result = {
+ 'ok': False,
+ 'message': "Minimum password length is 8 characters."
+ }
+ return result
+
+ pw_hash = argon2.hash(new_password)
+ async with request.app['pool'].acquire() as conn:
+ await conn.fetch(
+ "UPDATE virtual_users SET password = $1 WHERE buckler_id = $2",
+ pw_hash, user_id)
+ result = {
+ 'ok': True,
+ 'message': "Password has been changed."
+ }
+ return result
+
+
+async def new_email(request):
+ """Add a new email address."""
+ user_id = int(request.cookies.get('userid'))
+ data = await request.post()
+
+ new_password = data.get('new_password', '')
+ verify_new_password = data.get('verify_new_password', '')
+
+ if new_password != verify_new_password:
+ result = {
+ 'ok': False,
+ 'message': "New passwords do not match."
+ }
+ return result
+
+ if len(new_password) > config.max_password:
+ result = {
+ 'ok': False,
+ 'message': "Maximum password length is 1024 characters."
+ }
+ return result
+
+ if len(new_password) < config.min_password:
+ result = {
+ 'ok': False,
+ 'message': "Minimum password length is 8 characters."
+ }
+ return result
+
+ pw_hash = argon2.hash(new_password)
+ email = request['meta']['username'] + '@' + config.server_domain
+ async with request.app['pool'].acquire() as conn:
+ await conn.execute(
+ "INSERT INTO virtual_users "
+ "(domain_id, password, email, buckler_id) "
+ "VALUES (1, $1, $2, $3)",
+ pw_hash, email, user_id)
+ result = {
+ 'ok': True,
+ 'message': "New email account has been created."
+ }
+ return result
diff --git a/static/stickup.css b/static/stickup.css
index 3a64139..d8d296e 100644
--- a/static/stickup.css
+++ b/static/stickup.css
@@ -43,3 +43,8 @@ main {
.result_bad {
background-color: rgba(255, 0, 0, 0.6);
}
+
+ul {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
diff --git a/stickup.py b/stickup.py
index 5c5c190..2b9d8ac 100755
--- a/stickup.py
+++ b/stickup.py
@@ -12,6 +12,7 @@ import uvloop
import asyncpg
from passlib.hash import argon2
+import forms
import config
import buckler_aiohttp
@@ -23,56 +24,27 @@ routes = web.RouteTableDef()
async def index(request):
"""The index page."""
user_id = int(request.cookies.get('userid'))
+ server_domain = config.server_domain
+ result = {}
async with request.app['pool'].acquire() as conn:
- user_data = await conn.fetch(
+ user_data = await conn.fetchrow(
"SELECT * FROM virtual_users WHERE buckler_id = $1",
user_id)
- result = {}
+ if not user_data and request.method == 'GET':
+ return render_template('index.html', request, locals())
+
if request.method == 'POST':
data = await request.post()
- current_password = data.get('current_password', '')
- new_password = data.get('new_password', '')
- verify_new_password = data.get('verify_new_password', '')
-
- if not argon2.verify(current_password, user_data[0]['password']):
- result = {
- 'ok': False,
- 'message': "Current password does not match."
- }
- return render_template('index.html', request, locals())
-
- if new_password != verify_new_password:
- result = {
- 'ok': False,
- 'message': "New passwords do not match."
- }
- return render_template('index.html', request, locals())
-
- if len(new_password) > config.max_password:
- result = {
- 'ok': False,
- 'message': "Maximum password length is 1024 characters."
- }
- return render_template('index.html', request, locals())
-
- if len(new_password) < config.min_password:
- result = {
- 'ok': False,
- 'message': "Minimum password length is 8 characters."
- }
- return render_template('index.html', request, locals())
-
- pw_hash = argon2.hash(new_password)
- async with request.app['pool'].acquire() as conn:
- await conn.fetch(
- "UPDATE virtual_users SET password = $1 WHERE buckler_id = $2",
- pw_hash, user_id)
- result = {
- 'ok': True,
- 'message': "Password has been changed."
- }
+ form_type = data.get('form_type')
+ if form_type == 'change_password':
+ result = await forms.change_password(request, user_data)
+ elif form_type == 'new_email':
+ result = await forms.new_email(request)
+ if result['ok']:
+ email = request['meta']['username'] + '@' +config.server_domain
+ user_data = {'email': email}
return render_template('index.html', request, locals())
diff --git a/templates/index.html b/templates/index.html
index d460b7f..d5ffec1 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -12,31 +12,84 @@
This is a stickup!
- {% for record in user_data %}
- Your email address is {{ record['email'] }}
- {% endfor %}
{% if result %}
{{ result['message'] }}
{% endif %}
+ {% if user_data %}
+ Your email address is {{ user_data['email'] }}
+ {% else %}
+ There is no email address currently associated with your buckler account.
+ Make a new one:
+ New email address: {{ request['meta']['username'] }}@{{ server_domain }}
+
+ {% endif %}
+ Password requirements:
+
+ - Maximum length: 1024 characters
+ - Minimum length: 8 characters
+
+ Email server settings:
+
+
+ Server Domain |
+ mail.steelbea.me |
+
+
+ Supported Protocols |
+ IMAP, SMTP |
+
+
+ IMAP Port |
+ 993 |
+
+
+ SMTP Port |
+ 465 |
+
+
+ Connection Security |
+ SSL/TLS |
+
+
+ Authentication Method |
+ Normal password |
+
+