Update user cli commands

This commit is contained in:
Tim Van Baak 2020-04-23 21:07:07 -07:00
parent 773e6a23e0
commit dcf039c9de
3 changed files with 67 additions and 123 deletions

View File

@ -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

View File

@ -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 '<UserModel uid={0.id} username={0.username}>'.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

View File

@ -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,
]]