From dcf039c9de962b9e120fefc6caf4908444dfc243 Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Thu, 23 Apr 2020 21:07:07 -0700 Subject: [PATCH] Update user cli commands --- amanuensis/cli/user.py | 104 +++++++++++++++++++++--------------- amanuensis/user.py | 77 -------------------------- amanuensis/user/__init__.py | 9 +++- 3 files changed, 67 insertions(+), 123 deletions(-) delete mode 100644 amanuensis/user.py diff --git a/amanuensis/cli/user.py b/amanuensis/cli/user.py index e080f24..e129e6d 100644 --- a/amanuensis/cli/user.py +++ b/amanuensis/cli/user.py @@ -1,12 +1,20 @@ # Standard library imports import getpass -import os -import shutil +import logging +# import shutil # Module imports from amanuensis.cli.helpers import ( - add_argument, no_argument, requires_user, alias, - config_get, config_set, CONFIG_GET_ROOT_VALUE) + add_argument, + no_argument, + requires_user, + alias, + config_get, + config_set, + CONFIG_GET_ROOT_VALUE) +from amanuensis.models import UserModel + +logger = logging.getLogger(__name__) @alias('uc') @@ -18,26 +26,34 @@ def command_create(args): Create a user """ # Module imports - from amanuensis.config import logger from amanuensis.user import ( - UserModel, valid_username, valid_email, create_user) + valid_username, valid_email, create_user) # Verify arguments if not valid_username(args.username): logger.error("Invalid username: usernames may only contain alphanumer" "ic characters, dashes, and underscores") return -1 - if UserModel.by(name=args.username) is not None: - logger.error("Invalid username: username is already taken") - return -1 if not args.displayname: args.displayname = args.username if args.email and not valid_email(args.email): logger.error("Invalid email") return -1 + try: + existing_user = args.model_factory.user(args.username) + if existing_user is not None: + logger.error("Invalid username: username is already taken") + return -1 + except Exception: + pass # User doesn't already exist, good to go # Perform command - new_user, tmp_pw = create_user(args.username, args.displayname, args.email) + new_user, tmp_pw = create_user( + args.root, + args.model_factory, + args.username, + args.displayname, + args.email) # Output print(tmp_pw) @@ -50,41 +66,43 @@ def command_delete(args): """ Delete a user """ - # Module imports - from amanuensis.config import logger, prepend, json_rw + raise NotImplementedError() + # # Module imports + # from amanuensis.config import logger, prepend, json_rw - # Perform command - user_path = prepend('user', args.user.id) - shutil.rmtree(user_path) - with json_rw('user', 'index.json') as index: - del index[args.user.username] + # # Perform command + # user_path = prepend('user', args.user.id) + # shutil.rmtree(user_path) + # with json_rw('user', 'index.json') as index: + # del index[args.user.username] - # TODO resolve user id references in all games + # # TODO resolve user id references in all games - # Output - logger.info("Deleted user {0.username} ({0.id})".format(args.user)) - return 0 + # # Output + # logger.info("Deleted user {0.username} ({0.id})".format(args.user)) + # return 0 @alias('ul') @no_argument def command_list(args): """List all users""" - # Module imports - from amanuensis.config import prepend, json_ro - from amanuensis.user import UserModel + raise NotImplementedError() + # # Module imports + # from amanuensis.config import prepend, json_ro + # from amanuensis.user import UserModel - # Perform command - users = [] - with json_ro('user', 'index.json') as index: - for username, uid in index.items(): - users.append(UserModel.by(uid=uid)) + # # Perform command + # users = [] + # with json_ro('user', 'index.json') as index: + # for username, uid in index.items(): + # users.append(UserModel.by(uid=uid)) - # Output - users.sort(key=lambda u: u.username) - for user in users: - print("{0.id} {0.displayname} ({0.username})".format(user)) - return 0 + # # Output + # users.sort(key=lambda u: u.username) + # for user in users: + # print("{0.id} {0.displayname} ({0.username})".format(user)) + # return 0 @alias('un') @@ -99,8 +117,7 @@ def command_config(args): """ Interact with a user's config """ - # Module imports - from amanuensis.config import logger, json_rw + user: UserModel = args.user # Verify arguments if args.get and args.set: @@ -109,11 +126,11 @@ def command_config(args): # Perform command if args.get: - config_get(args.user.config, args.get) + config_get(user.cfg, args.get) if args.set: - with json_rw(args.user.config_path) as cfg: - config_set(args.user.id, cfg, args.set) + with user.ctx.edit_config() as cfg: + config_set(user.uid, cfg, args.set) # Output return 0 @@ -127,15 +144,14 @@ def command_passwd(args): """ Set a user's password """ - # Module imports - from amanuensis.config import logger + user: UserModel = args.user # Verify arguments - pw = args.password or getpass.getpass("Password: ") + password: str = args.password or getpass.getpass("Password: ") # Perform command - args.user.set_password(pw) + user.set_password(password) # Output - logger.info('Updated password for {}'.format(args.user.username)) + logger.info('Updated password for {}'.format(user.cfg.username)) return 0 diff --git a/amanuensis/user.py b/amanuensis/user.py deleted file mode 100644 index bde6532..0000000 --- a/amanuensis/user.py +++ /dev/null @@ -1,77 +0,0 @@ -import os -import re -import time -import uuid - -from flask_login import UserMixin, AnonymousUserMixin -from werkzeug.security import generate_password_hash, check_password_hash - -from amanuensis.errors import ( - ArgumentError, MissingConfigError, IndexMismatchError) -from amanuensis.config import prepend, json_rw, root -from amanuensis.resources import get_stream - - -class UserModel(UserMixin): - @staticmethod - def by(uid=None, name=None): - """ - Gets the UserModel with the given uid or username - - If the uid or name simply does not match an existing user, returns - None. If the uid matches the index but there is something wrong with - the user's config, raises an error. - """ - if uid and name: - raise ArgumentError("uid and name both specified to UserModel.by()") - if not uid and not name: - raise ArgumentError("One of uid or name must be not None") - if not uid: - with root.user.index() as index: - uid = index.get(name) - if not uid: - return None - if not os.path.isdir(prepend('user', uid)): - raise IndexMismatchError("username={} uid={}".format(name, uid)) - if not os.path.isfile(prepend('user', uid, 'config.json')): - raise MissingConfigError("uid={}".format(uid)) - return UserModel(uid) - - def __init__(self, uid): - """User model initializer, assume all checks were done by by()""" - self.id = str(uid) # Flask-Login checks for this - self.config_path = prepend('user', uid, 'config.json') - self.ctx = root.user[self.id] - with self.ctx.config() as j: - self.config = j - - def __getattr__(self, key): - if key not in self.config: - raise AttributeError(key) - return self.config.get(key) - - def __str__(self): - return '<{0.username}>'.format(self) - - def __repr__(self): - return ''.format(self) - - def set_password(self, pw): - h = generate_password_hash(pw) - with self.ctx.config(edit=True) as j: - j['password'] = h - - def check_password(self, pw): - with self.ctx.config() as cfg: - return check_password_hash(cfg.password, pw) - - def in_lexicon(self, lexicon): - return self.id in lexicon.join.joined - - -class AnonymousUserModel(AnonymousUserMixin): - is_admin = False - - def in_lexicon(self, lexicon): - return False - diff --git a/amanuensis/user/__init__.py b/amanuensis/user/__init__.py index 67d4d8e..f3ba749 100644 --- a/amanuensis/user/__init__.py +++ b/amanuensis/user/__init__.py @@ -1,5 +1,10 @@ -from amanuensis.user.signup import create_user +from amanuensis.user.signup import ( + create_user, + valid_username, + valid_email) __all__ = [member.__name__ for member in [ - create_user + create_user, + valid_username, + valid_email, ]]