add new account creation

This commit is contained in:
iou1name 2020-11-21 14:23:34 -05:00
parent 366ed98ef8
commit ec28f16031
5 changed files with 180 additions and 49 deletions

View File

@ -21,3 +21,5 @@ mailserver_db = {
'host': 'localhost',
'port': 5432,
}
max_password = 1024
min_password = 8

99
forms.py Normal file
View File

@ -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

View File

@ -43,3 +43,8 @@ main {
.result_bad {
background-color: rgba(255, 0, 0, 0.6);
}
ul {
margin-top: 0.5em;
margin-bottom: 0.5em;
}

View File

@ -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())

View File

@ -12,31 +12,84 @@
<h1>This is a stickup!</h1>
</header>
<main>
{% for record in user_data %}
<div>Your email address is {{ record['email'] }}</div>
{% endfor %}
{% if result %}
<div class="result_message result_{% if result['ok'] %}good{% else %}bad{% endif %}">{{ result['message'] }}</div>
{% endif %}
{% if user_data %}
<div>Your email address is <b>{{ user_data['email'] }}</b></div>
<form method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="form_type" value="change_password">
<table>
<tr>
<td><label for="current_password">Current password</label></td>
<td><input id="current_password" name="current_password" type="password"></td>
<td><input id="current_password" name="current_password" type="password" maxlength="1024" minlength="8"></td>
</tr>
<tr>
<td><label for="new_password">New password</label></td>
<td><input id="new_password" name="new_password" type="password"></td>
<td><input id="new_password" name="new_password" type="password" maxlength="1024" minlength="8"></td>
</tr>
<tr>
<td><label for="verify_new_password">Verify new password</label></td>
<td><input id="verify_new_password" name="verify_new_password" type="password"></td>
<td><input id="verify_new_password" name="verify_new_password" type="password" maxlength="1024" minlength="8"></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
{% else %}
<div>There is no email address currently associated with your buckler account.</div>
<h3>Make a new one:</h3>
<div>New email address: <b>{{ request['meta']['username'] }}@{{ server_domain }}</b></div>
<form method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="form_type" value="new_email">
<table>
<tr>
<td><label for="new_password">New password</label></td>
<td><input id="new_password" name="new_password" type="password" maxlength="1024" minlength="8"></td>
</tr>
<tr>
<td><label for="verify_new_password">Verify new password</label></td>
<td><input id="verify_new_password" name="verify_new_password" type="password" maxlength="1024" minlength="8"></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
{% endif %}
<p>Password requirements:</p>
<ul>
<li>Maximum length: 1024 characters</li>
<li>Minimum length: 8 characters</li>
</ul>
<p>Email server settings:</p>
<table>
<tr>
<td>Server Domain</td>
<td>mail.steelbea.me</td>
</tr>
<tr>
<td>Supported Protocols</td>
<td>IMAP, SMTP</td>
</tr>
<tr>
<td>IMAP Port</td>
<td>993</td>
</tr>
<tr>
<td>SMTP Port</td>
<td>465</td>
</tr>
<tr>
<td>Connection Security</td>
<td>SSL/TLS</td>
</tr>
<tr>
<td>Authentication Method</td>
<td>Normal password</td>
</tr>
</table>
</main>
</body>
</html>