From 58911a2da49f8b9da186fe890cbee52ffbd8706a Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Thu, 16 Jan 2020 23:49:37 -0800 Subject: [PATCH] Bring user creation entirely under user module --- amanuensis/cli/user.py | 5 ++-- amanuensis/config/__init__.py | 16 +--------- amanuensis/server/home.py | 2 +- amanuensis/templates/home/home.html | 2 +- amanuensis/user.py | 45 ++++++++++++++++++++--------- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/amanuensis/cli/user.py b/amanuensis/cli/user.py index 576b751..376332b 100644 --- a/amanuensis/cli/user.py +++ b/amanuensis/cli/user.py @@ -18,7 +18,7 @@ def command_create(args): if not user.valid_username(args.username): config.logger.error("Invalid username: usernames may only contain alphanumeric characters, dashes, and underscores") 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") return -1 if not args.displayname: @@ -28,9 +28,10 @@ def command_create(args): if not user.valid_email(args.email): config.logger.error("Invalid email") return -1 + # Create user 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("Username: {}\nUser ID: {}\nPassword: {}".format(args.username, new_user.uid, tmp_pw)) diff --git a/amanuensis/config/__init__.py b/amanuensis/config/__init__.py index 104c7b7..96e152c 100644 --- a/amanuensis/config/__init__.py +++ b/amanuensis/config/__init__.py @@ -56,18 +56,4 @@ def json_ro(*path): return config.loader.json_ro(prepend(*path)) def json_rw(*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'] + return config.loader.json_rw(prepend(*path)) \ No newline at end of file diff --git a/amanuensis/server/home.py b/amanuensis/server/home.py index 6083b29..45d283a 100644 --- a/amanuensis/server/home.py +++ b/amanuensis/server/home.py @@ -22,7 +22,7 @@ def get_bp(): @bp.route('/admin/', methods=['GET']) @login_required def admin(): - if not current_user.admin: + if not current_user.is_admin: return redirect(url_for('home.home')) with config.json_ro('config.json') as j: diff --git a/amanuensis/templates/home/home.html b/amanuensis/templates/home/home.html index b4cec9b..7969784 100644 --- a/amanuensis/templates/home/home.html +++ b/amanuensis/templates/home/home.html @@ -6,7 +6,7 @@ {% block sb_logout %}Log out{% endblock %} {% set template_sidebar_rows = [self.sb_topline(), self.sb_logout()] %} -{% if current_user.admin %} +{% if current_user.is_admin %} {% block sb_admin %}Admin{% endblock %} {% set template_sidebar_rows = template_sidebar_rows + [self.sb_admin()] %} {% endif %} diff --git a/amanuensis/user.py b/amanuensis/user.py index ddbb89d..7b7b421 100644 --- a/amanuensis/user.py +++ b/amanuensis/user.py @@ -7,13 +7,16 @@ from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash import config +import resources class User(UserMixin): def __init__(self, uid): if not os.path.isdir(config.prepend('user', uid)): raise ValueError("No user with uid {}".format(uid)) - self.uid = str(uid) - self.config_path = os.path.join('user', uid, 'config.json') + if not os.path.isfile(config.prepend('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: self.config = j @@ -45,26 +48,40 @@ def valid_email(email): return re.match(addrspec, email) def create_user(username, displayname, email): + """ + Creates a new user + """ + # Validate arguments if not valid_username(username): raise ValueError("Invalid username: '{}'".format(username)) if not valid_email(email): raise ValueError("Invalid email: '{}'".format(email)) + + # Create the user directory and initialize it with a blank user 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() - 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.set_password(temp_pw) + return u, temp_pw def uid_from_username(username):