Wire up basic user login
This commit is contained in:
parent
65049d8202
commit
fcaa68850e
|
@ -179,7 +179,7 @@ def command_user_passwd(args):
|
||||||
|
|
||||||
if not args.username:
|
if not args.username:
|
||||||
args.username = input("Username: ")
|
args.username = input("Username: ")
|
||||||
uid = get_user_by_username(args.username)
|
uid = uid_from_username(args.username)
|
||||||
if uid is None:
|
if uid is None:
|
||||||
print("No user with username '{}'".format(args.username))
|
print("No user with username '{}'".format(args.username))
|
||||||
return -1
|
return -1
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
from flask import Flask, render_template
|
from flask import Flask, render_template
|
||||||
|
from flask_login import LoginManager
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
from server.auth import get_bp as get_auth_bp
|
||||||
|
|
||||||
app = Flask(__name__, template_folder="../templates")
|
app = Flask(__name__, template_folder="../templates")
|
||||||
app.secret_key = bytes.fromhex(config.get('secret_key'))
|
app.secret_key = bytes.fromhex(config.get('secret_key'))
|
||||||
|
login = LoginManager(app)
|
||||||
from server.auth import bp
|
auth_bp = get_auth_bp(login)
|
||||||
app.register_blueprint(auth.bp)
|
app.register_blueprint(auth_bp)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import flask
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, PasswordField, BooleanField, SubmitField
|
||||||
|
from wtforms.validators import DataRequired
|
||||||
|
from flask_login import current_user, login_user
|
||||||
|
|
||||||
|
import config
|
||||||
|
import user
|
||||||
|
|
||||||
|
class LoginForm(FlaskForm):
|
||||||
|
username = StringField('Username', validators=[DataRequired()])
|
||||||
|
#password = PasswordField('Password', validators=[DataRequired()])
|
||||||
|
#remember = BooleanField('Remember Me')
|
||||||
|
submit = SubmitField('Log in')
|
||||||
|
|
||||||
|
def get_bp(login_manager):
|
||||||
|
"""Create a blueprint for the auth functions"""
|
||||||
|
bp = flask.Blueprint('auth', __name__, url_prefix='/auth')
|
||||||
|
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(uid):
|
||||||
|
return user.user_from_uid(str(uid))
|
||||||
|
|
||||||
|
@bp.route('/login/', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
form = LoginForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
username = form.username.data
|
||||||
|
uid = user.uid_from_username(username)
|
||||||
|
if uid is None:
|
||||||
|
pass
|
||||||
|
u = user.user_from_uid(uid)
|
||||||
|
login_user(u)
|
||||||
|
config.logger.info("Logged in user '{}' ({})".format(u.get('username'), u.uid))
|
||||||
|
name = u.get('username')
|
||||||
|
else:
|
||||||
|
name = "guest"
|
||||||
|
return flask.render_template('auth/login.html', form=form, username=name)
|
||||||
|
|
||||||
|
return bp
|
|
@ -1,6 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<h1>Hello, {{username}}</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Hello, {{username}}</h1>
|
||||||
|
{% if current_user.is_authenticated %}{{ current_user.get('displayname') }}{% endif %}
|
||||||
|
<form action="" method="post" novalidate>
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<p>{{ form.username.label }}<br>{{ form.username(size=32) }}</p>
|
||||||
|
<p>{{ form.submit() }}</p>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -3,24 +3,33 @@ import re
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from flask_login import UserMixin
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
|
||||||
class User():
|
class User(UserMixin):
|
||||||
def __init__(self, uid):
|
def __init__(self, uid):
|
||||||
if not os.path.isdir(config.prepend('user', uid)):
|
if not os.path.isdir(config.prepend('user', uid)):
|
||||||
raise ValueError("No user with uid {}".format(uid))
|
raise ValueError("No user with uid {}".format(uid))
|
||||||
self.uid = uid
|
self.uid = str(uid)
|
||||||
self.config = os.path.join('user', uid, 'config.json')
|
self.config_path = os.path.join('user', uid, 'config.json')
|
||||||
|
with config.json_ro(self.config_path) as j:
|
||||||
|
self.config = j
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.uid
|
||||||
|
|
||||||
|
def get(self, key):
|
||||||
|
return self.config.get(key)
|
||||||
|
|
||||||
def set_password(self, pw):
|
def set_password(self, pw):
|
||||||
h = generate_password_hash(pw)
|
h = generate_password_hash(pw)
|
||||||
with config.json_rw(self.config) as j:
|
with config.json_rw(self.config_path) as j:
|
||||||
j['password'] = h
|
j['password'] = h
|
||||||
|
|
||||||
def check_password(self, pw):
|
def check_password(self, pw):
|
||||||
with config.json_ro(self.config) as j:
|
with config.json_ro(self.config_path) as j:
|
||||||
return check_password_hash(j['password'], pw)
|
return check_password_hash(j['password'], pw)
|
||||||
|
|
||||||
def valid_username(username):
|
def valid_username(username):
|
||||||
|
@ -34,6 +43,10 @@ def valid_email(email):
|
||||||
return re.match(addrspec, email)
|
return re.match(addrspec, email)
|
||||||
|
|
||||||
def create_user(username, displayname, email):
|
def create_user(username, displayname, email):
|
||||||
|
if not valid_username(username):
|
||||||
|
raise ValueError("Invalid username: '{}'".format(username))
|
||||||
|
if not valid_email(email):
|
||||||
|
raise ValueError("Invalid email: '{}'".format(email))
|
||||||
uid = uuid.uuid4().hex
|
uid = uuid.uuid4().hex
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
temp_pw = os.urandom(32).hex()
|
temp_pw = os.urandom(32).hex()
|
||||||
|
@ -51,6 +64,20 @@ def create_user(username, displayname, email):
|
||||||
u.set_password(temp_pw)
|
u.set_password(temp_pw)
|
||||||
return u, temp_pw
|
return u, temp_pw
|
||||||
|
|
||||||
def get_user_by_username(username):
|
def uid_from_username(username):
|
||||||
|
"""Gets the internal uid of a user given a username"""
|
||||||
|
if username is None:
|
||||||
|
raise ValueError("username must not be None")
|
||||||
|
if not username:
|
||||||
|
raise ValueError("username must not be empty")
|
||||||
with config.json_ro('user', 'index.json') as index:
|
with config.json_ro('user', 'index.json') as index:
|
||||||
return index.get(username)
|
uid = index.get(username)
|
||||||
|
if uid is None:
|
||||||
|
config.logger.debug("uid_from_username('{}') returned None".format(username))
|
||||||
|
return uid
|
||||||
|
|
||||||
|
def user_from_uid(uid):
|
||||||
|
if not os.path.isdir(config.prepend('user', uid)):
|
||||||
|
config.logger.debug("No user with uid '{}'".format(uid))
|
||||||
|
return None
|
||||||
|
return User(uid)
|
||||||
|
|
Loading…
Reference in New Issue