Add a login page (nonfunctional)

This commit is contained in:
Juhani Krekelä 2018-06-09 17:25:04 +03:00
parent c3556b0c71
commit 0187775332
3 changed files with 99 additions and 2 deletions

View File

@ -3,10 +3,14 @@ import random
import unicodedata import unicodedata
import sqlite3 import sqlite3
from collections import namedtuple
from passlib.hash import argon2 from passlib.hash import argon2
import config import config
UserInfo = namedtuple('UserInfo', ('id', 'parent', 'status', 'username', 'email', 'comment'))
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# General # General
# ------------------------------------------------------------------ # ------------------------------------------------------------------
@ -29,6 +33,7 @@ def connect():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def add_user(db, *, username, password, email, parent, status): def add_user(db, *, username, password, email, parent, status):
# TODO: Ensure users are unique
"""Add a user to the database """Add a user to the database
Will not commit the changes itself, so run .commit() on the database object yourself""" Will not commit the changes itself, so run .commit() on the database object yourself"""
global csprgn global csprgn
@ -57,6 +62,65 @@ def add_user(db, *, username, password, email, parent, status):
cursor.execute('PRAGMA foreign_keys = ON;') # Fail if we insert a user with bogus parent field cursor.execute('PRAGMA foreign_keys = ON;') # Fail if we insert a user with bogus parent field
cursor.execute('INSERT INTO users VALUES (?, ?, ?, ?, ?, ?, ?);', (userid, parent, status, password, username, email, '')) cursor.execute('INSERT INTO users VALUES (?, ?, ?, ?, ?, ?, ?);', (userid, parent, status, password, username, email, ''))
def get_userid(db, username):
"""Returns the user ID associated with given username
If no user was found, returns None"""
# Unicode normalize the username
username = unicodedata.normalize('NFKC', username)
# Get the user ID
cursor = db.cursor()
cursor.execute('SELECT id FROM users WHERE username = ?', (username,))
results = cursor.fetchall()
# If no user was found, return None
if len(results) != 1:
return None
return results[0][0]
def check_password(db, userid, password):
"""Checks the password for given userid
Will return True if the password matches and False otherwise"""
# Unicode normalize the password
password = unicodedata.normalize('NFKC', password)
# Get the password and status
cursor = db.cursor()
cursor.execute('SELECT password, status FROM users WHERE id = ?', (userid,))
results = cursor.fetchall()
# If no user of that name, fail
if len(results) != 1:
return False
hashed, status = results[0]
# If user has been deleted, fail
if status == userstatus.deleted:
return False
# Check the password
return argon2.verify(password, hashed)
def get_user_info(db, userid):
"""Returns a UserInfo object representing the data associated with a user
If no user was found, returns None"""
cursor = db.cursor()
cursor.execute('SELECT id, parent, status, username, email, comment FROM users WHERE id = ?', (userid,))
results = cursor.fetchall()
# If no user was found, return None
if len(results) != 1:
return None
userid, parent, status, username, email, comment = results[0]
# Translate status into enum
status = userstatus(status)
return UserInfo(userid, parent, status, username, email, comment)
def initialize_users(db, admin_user, admin_password): def initialize_users(db, admin_user, admin_password):
"""Creates a bare-bones user table with only admin user """Creates a bare-bones user table with only admin user
This should never be run outside of the initialization script""" This should never be run outside of the initialization script"""

View File

@ -90,6 +90,31 @@ def index():
soup = new_soup() soup = new_soup()
return page_skeleton(page_title = config.site_name, contents = [], soup = soup) return page_skeleton(page_title = config.site_name, contents = [], soup = soup)
def login_forward(raw_path):
"""Returns html
Creates a page telling the user to log in"""
# TODO: Take the user back to where they were
soup = new_soup()
# TODO: Don't hardcode
contents = bs4.BeautifulSoup('''
<p>Login to access</p>
<form action="''' + config.url_prefix + '''/login" method="post">
<div>
<input type="text" name="username"/>
</div>
<div>
<input type="password" name="password"/>
</div>
<div>
<input type="submit" value="Login"/>
</div>
</form>
''')
# TODO: Internationalization
return page_skeleton(page_title = 'Login to ' + config.site_name, contents = contents, soup = soup)
def error_404(path): def error_404(path):
"""Returns html""" """Returns html"""
soup = new_soup() soup = new_soup()

View File

@ -7,7 +7,9 @@ import generate_html
class HTTPRequestHandler(http.server.BaseHTTPRequestHandler): class HTTPRequestHandler(http.server.BaseHTTPRequestHandler):
server_version = 'Buranun/0.0' server_version = 'Buranun/0.0'
protocol_version = 'HTTP/1.1' # TODO: Look into keepalive problems in links2
#protocol_version = 'HTTP/1.1'
protocol_version = 'HTTP/1.0'
def __send_html(self, html, *, status_code = 200): def __send_html(self, html, *, status_code = 200):
encoded = html.encode('utf-8') encoded = html.encode('utf-8')
@ -54,7 +56,13 @@ class HTTPRequestHandler(http.server.BaseHTTPRequestHandler):
print(received_cookies['buranun_session'].value) print(received_cookies['buranun_session'].value)
else: else:
print('no cookies') # Display page that tells user to login
# TODO: Have it forward the user back to the page where they were at
html = generate_html.login_forward(self.path)
self.__send_html(html)
# Don't run rest of the function
return
path = urllib.parse.unquote(self.path) path = urllib.parse.unquote(self.path)