Bring user creation entirely under user module

This commit is contained in:
Tim Van Baak 2020-01-16 23:49:37 -08:00
parent 4c41407d69
commit 58911a2da4
5 changed files with 37 additions and 33 deletions

View File

@ -18,7 +18,7 @@ def command_create(args):
if not user.valid_username(args.username): if not user.valid_username(args.username):
config.logger.error("Invalid username: usernames may only contain alphanumeric characters, dashes, and underscores") config.logger.error("Invalid username: usernames may only contain alphanumeric characters, dashes, and underscores")
return -1 return -1
if user.get_user_by_username(args.username) is not None: if user.uid_from_username(args.username) is not None:
config.logger.error("Invalid username: username is already taken") config.logger.error("Invalid username: username is already taken")
return -1 return -1
if not args.displayname: if not args.displayname:
@ -28,9 +28,10 @@ def command_create(args):
if not user.valid_email(args.email): if not user.valid_email(args.email):
config.logger.error("Invalid email") config.logger.error("Invalid email")
return -1 return -1
# Create user # Create user
new_user, tmp_pw = user.create_user(args.username, args.displayname, args.email) new_user, tmp_pw = user.create_user(args.username, args.displayname, args.email)
with config.json_ro(new_user.config) as js: with config.json_ro(new_user.config_path) as js:
print(json.dumps(js, indent=2)) print(json.dumps(js, indent=2))
print("Username: {}\nUser ID: {}\nPassword: {}".format(args.username, new_user.uid, tmp_pw)) print("Username: {}\nUser ID: {}\nPassword: {}".format(args.username, new_user.uid, tmp_pw))

View File

@ -56,18 +56,4 @@ def json_ro(*path):
return config.loader.json_ro(prepend(*path)) return config.loader.json_ro(prepend(*path))
def json_rw(*path): def json_rw(*path):
return config.loader.json_rw(prepend(*path)) return config.loader.json_rw(prepend(*path))
def new_user(user_json):
user_dir = prepend("user", user_json['uid'])
# Create user dir and put config in it
os.mkdir(user_dir)
with open_ex(user_dir, "config.json", mode='w') as f:
json.dump(user_json, f, allow_nan=False, indent='\t')
# Ensure index exists
if not os.path.isfile(prepend('user', 'index.json')):
with open_ex('user', 'index.json', mode='w') as f:
json.dump({}, f)
# Update index
with json_rw('user', 'index.json') as j:
j[user_json['username']] = user_json['uid']

View File

@ -22,7 +22,7 @@ def get_bp():
@bp.route('/admin/', methods=['GET']) @bp.route('/admin/', methods=['GET'])
@login_required @login_required
def admin(): def admin():
if not current_user.admin: if not current_user.is_admin:
return redirect(url_for('home.home')) return redirect(url_for('home.home'))
with config.json_ro('config.json') as j: with config.json_ro('config.json') as j:

View File

@ -6,7 +6,7 @@
{% block sb_logout %}<a href="{{ url_for('auth.logout') }}">Log out</a>{% endblock %} {% block sb_logout %}<a href="{{ url_for('auth.logout') }}">Log out</a>{% endblock %}
{% set template_sidebar_rows = [self.sb_topline(), self.sb_logout()] %} {% set template_sidebar_rows = [self.sb_topline(), self.sb_logout()] %}
{% if current_user.admin %} {% if current_user.is_admin %}
{% block sb_admin %}<a href="{{ url_for('home.admin') }}">Admin</a>{% endblock %} {% block sb_admin %}<a href="{{ url_for('home.admin') }}">Admin</a>{% endblock %}
{% set template_sidebar_rows = template_sidebar_rows + [self.sb_admin()] %} {% set template_sidebar_rows = template_sidebar_rows + [self.sb_admin()] %}
{% endif %} {% endif %}

View File

@ -7,13 +7,16 @@ 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
import resources
class User(UserMixin): 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 = str(uid) if not os.path.isfile(config.prepend('user', uid, 'config.json')):
self.config_path = os.path.join('user', uid, 'config.json') raise FileNotFoundError("User {} missing config.json".format(uid))
self.id = str(uid) # Flask-Login checks for this
self.config_path = config.prepend('user', uid, 'config.json')
with config.json_ro(self.config_path) as j: with config.json_ro(self.config_path) as j:
self.config = j self.config = j
@ -45,26 +48,40 @@ 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):
"""
Creates a new user
"""
# Validate arguments
if not valid_username(username): if not valid_username(username):
raise ValueError("Invalid username: '{}'".format(username)) raise ValueError("Invalid username: '{}'".format(username))
if not valid_email(email): if not valid_email(email):
raise ValueError("Invalid email: '{}'".format(email)) raise ValueError("Invalid email: '{}'".format(email))
# Create the user directory and initialize it with a blank user
uid = uuid.uuid4().hex uid = uuid.uuid4().hex
now = int(time.time()) user_dir = config.prepend("user", uid)
os.mkdir(user_dir)
with resources.get_stream("user.json") as s:
with open(config.prepend(user_dir, 'config.json'), 'wb') as f:
f.write(s.read())
# Fill out the new user
with config.json_rw(user_dir, 'config.json') as cfg:
cfg['uid'] = uid
cfg['username'] = username
cfg['displayname'] = displayname
cfg['email'] = email
cfg['created'] = int(time.time())
# Update the index with the new user
with config.json_rw('user', 'index.json') as index:
index[username] = uid
# Set a temporary password
temp_pw = os.urandom(32).hex() temp_pw = os.urandom(32).hex()
user_json = {
'uid': uid,
'username': username,
'displayname': displayname,
'email': email,
'password': None,
'created': now,
'newPasswordRequired': True,
'admin': False,
}
config.new_user(user_json)
u = User(uid) u = User(uid)
u.set_password(temp_pw) u.set_password(temp_pw)
return u, temp_pw return u, temp_pw
def uid_from_username(username): def uid_from_username(username):