diff --git a/init_sqlite.sh b/init_sqlite.sh index e0dd679..040659d 100755 --- a/init_sqlite.sh +++ b/init_sqlite.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash SQLITE=sqlite3 +PYTHON=python3 set -e @@ -10,7 +11,19 @@ then exit 1 fi -$SQLITE $1 -init schema.txt "insert into config ( +if [ -e "$1" ] +then + echo "Database '$1' already exists" >&2 + exit 1 +fi + +read -p 'Admin username: ' username +read -sp 'Admin password: ' password + +password=$($PYTHON tool.py password "$password") +time=$($PYTHON -c 'import time; print(time.time_ns())') + +$SQLITE "$1" -init schema.txt "insert into config ( version, name, description, @@ -25,4 +38,10 @@ values ( '$(head -c 30 /dev/urandom | base64)', '$(head -c 30 /dev/urandom | base64)', 0 -);" +); + +insert into users (name, password, role, join_time) +values (lower('$username'), '$password', 2, $time); +" + +echo "Database '$1' created" >&2 diff --git a/main.py b/main.py index 9e67c05..34b2884 100644 --- a/main.py +++ b/main.py @@ -8,7 +8,7 @@ import os, sys, subprocess import passlib.hash, secrets import time from datetime import datetime -import captcha +import captcha, password app = Flask(__name__) db = DB(os.getenv('DB')) @@ -103,7 +103,7 @@ def login(): v = db.get_user_password(request.form['username']) if v is not None: id, hash = v - if verify_password(request.form['password'], hash): + if password.verify(request.form['password'], hash): flash('Logged in', 'success') session['user_id'] = id return redirect(url_for('index')) @@ -155,8 +155,8 @@ def user_edit_password(): flash('New password must be at least 8 characters long', 'error') else: hash, = db.get_user_password_by_id(user_id) - if verify_password(request.form['old'], hash): - if db.set_user_password(user_id, hash_password(new)): + if password.verify(request.form['old'], hash): + if db.set_user_password(user_id, password.hash(new)): flash('Updated password', 'success') else: flash('Failed to update password', 'error') @@ -361,7 +361,7 @@ def register(): request.form['answer'], ): flash('CAPTCHA answer is incorrect', 'error') - elif not db.register_user(username, hash_password(password), time.time_ns()): + elif not db.register_user(username, password.hash(password), time.time_ns()): flash('Failed to create account (username may already be taken)', 'error') else: flash('Account has been created. You can login now.', 'success') @@ -522,7 +522,7 @@ def admin_new_user(): name, password = request.form['name'], request.form['password'] if name == '' or password == '': flash('Name and password may not be empty') - elif db.add_user(name, hash_password(password), time.time_ns()): + elif db.add_user(name, password.hash(password), time.time_ns()): flash('Added user', 'success') else: flash('Failed to add user', 'error') @@ -678,13 +678,6 @@ def utility_processor(): } -def hash_password(password): - return passlib.hash.argon2.hash(password) - -def verify_password(password, hash): - return passlib.hash.argon2.verify(password, hash) - - def restart(): ''' Shut down *all* workers and spawn new ones. diff --git a/password.py b/password.py new file mode 100644 index 0000000..34583c0 --- /dev/null +++ b/password.py @@ -0,0 +1,9 @@ +import passlib.hash + +def hash(password): + return passlib.hash.argon2.hash(password) + +def verify(password, hash): + return passlib.hash.argon2.verify(password, hash) + + diff --git a/tool.py b/tool.py new file mode 100755 index 0000000..537ef86 --- /dev/null +++ b/tool.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import sys, password + +def arg(i, s): + if i < len(sys.argv): + return sys.argv[i] + print(s) + sys.exit(1) + +def arg_last(i, s): + if i == len(sys.argv) - 1: + return sys.argv[i] + print(s) + sys.exit(1) + +proc = 'tool.py' if len(sys.argv) < 1 else sys.argv[0] +cmd = arg(1, f'usage: {proc} [...]') + +if cmd == 'password': + pwd = arg_last(2, 'usage: {proc} password ') + print(password.hash(pwd)) +else: + print('unknown command ', cmd) + sys.exit(1)