Move user creation code to new submodule
This commit is contained in:
parent
50216281b2
commit
1dd87fc6f0
|
@ -75,59 +75,3 @@ class AnonymousUserModel(AnonymousUserMixin):
|
||||||
def in_lexicon(self, lexicon):
|
def in_lexicon(self, lexicon):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def valid_username(username):
|
|
||||||
"""
|
|
||||||
A valid username is at least three characters long and composed solely of
|
|
||||||
alpahnumerics, dashes, and underscores. Additionally, usernames may not
|
|
||||||
be 32 hex digits, since that may be confused for an internal id.
|
|
||||||
"""
|
|
||||||
length_and_characters = re.match(r"^[A-Za-z0-9-_]{3,}$", username)
|
|
||||||
is_a_guid = re.match(r"^[A-Za-z0-9]{32}$", username)
|
|
||||||
return length_and_characters and not is_a_guid
|
|
||||||
|
|
||||||
|
|
||||||
def valid_email(email):
|
|
||||||
"""Vaguely RFC2822 email verifier"""
|
|
||||||
atom = r"[0-9A-Za-z!#$%&'*+-/=?^_`{|}~]{1,}"
|
|
||||||
dotatom = atom + r"(\." + atom + r")*"
|
|
||||||
addrspec = "^" + dotatom + "@" + dotatom + "$"
|
|
||||||
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 email and 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
|
|
||||||
user_dir = prepend("user", uid)
|
|
||||||
os.mkdir(user_dir)
|
|
||||||
with get_stream("user.json") as s:
|
|
||||||
with open(prepend(user_dir, 'config.json'), 'wb') as f:
|
|
||||||
f.write(s.read())
|
|
||||||
|
|
||||||
# Fill out the new user
|
|
||||||
with 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 json_rw('user', 'index.json') as index:
|
|
||||||
index[username] = uid
|
|
||||||
|
|
||||||
# Set a temporary password
|
|
||||||
temp_pw = os.urandom(32).hex()
|
|
||||||
u = UserModel.by(uid=uid)
|
|
||||||
u.set_password(temp_pw)
|
|
||||||
|
|
||||||
return u, temp_pw
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
from amanuensis.user.signup import create_user
|
||||||
|
|
||||||
|
__all__ = [member.__name__ for member in [
|
||||||
|
create_user
|
||||||
|
]]
|
|
@ -0,0 +1,77 @@
|
||||||
|
"""
|
||||||
|
Submodule encapsulating functionality pertaining to creating users in
|
||||||
|
an Amanuensis instance.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
from typing import Tuple
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from amanuensis.config import RootConfigDirectoryContext
|
||||||
|
from amanuensis.errors import ArgumentError
|
||||||
|
from amanuensis.models import ModelFactory, UserModel
|
||||||
|
from amanuensis.resources import get_stream
|
||||||
|
|
||||||
|
|
||||||
|
def valid_username(username: str) -> bool:
|
||||||
|
"""
|
||||||
|
A valid username is at least three characters long and composed solely of
|
||||||
|
alpahnumerics, dashes, and underscores. Additionally, usernames may not
|
||||||
|
be 32 hex digits, since that may be confused for an internal id.
|
||||||
|
"""
|
||||||
|
length_and_characters = re.match(r'^[A-Za-z0-9-_]{3,}$', username)
|
||||||
|
is_a_guid = re.match(r'^[A-Za-z0-9]{32}$', username)
|
||||||
|
return bool(length_and_characters and not is_a_guid)
|
||||||
|
|
||||||
|
|
||||||
|
def valid_email(email: str) -> bool:
|
||||||
|
"""Vaguely RFC2822 email verifier"""
|
||||||
|
atom = r"[0-9A-Za-z!#$%&'*+-/=?^_`{|}~]{1,}"
|
||||||
|
dotatom = atom + r"(\." + atom + r")*"
|
||||||
|
addrspec = '^' + dotatom + '@' + dotatom + '$'
|
||||||
|
return bool(re.match(addrspec, email))
|
||||||
|
|
||||||
|
|
||||||
|
def create_user(
|
||||||
|
root: RootConfigDirectoryContext,
|
||||||
|
model_factory: ModelFactory,
|
||||||
|
username: str,
|
||||||
|
displayname: str,
|
||||||
|
email: str) -> Tuple[UserModel, str]:
|
||||||
|
"""
|
||||||
|
Creates a new user
|
||||||
|
"""
|
||||||
|
# Validate arguments
|
||||||
|
if not valid_username(username):
|
||||||
|
raise ArgumentError('Invalid username: "{}"'.format(username))
|
||||||
|
if email and not valid_email(email):
|
||||||
|
raise ArgumentError('Invalid email: "{}"'.format(email))
|
||||||
|
|
||||||
|
# Create the user directory and config file
|
||||||
|
uid: str = uuid.uuid4().hex
|
||||||
|
user_dir: str = os.path.join(root.user.path, uid)
|
||||||
|
os.mkdir(user_dir)
|
||||||
|
with get_stream('user.json') as s:
|
||||||
|
path: str = os.path.join(user_dir, 'config.json')
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
f.write(s.read())
|
||||||
|
|
||||||
|
# Create the user index entry
|
||||||
|
with root.user.edit_index() as index:
|
||||||
|
index[username] = uid
|
||||||
|
|
||||||
|
# Fill out the new user
|
||||||
|
with root.user[uid].edit_config() as cfg:
|
||||||
|
cfg.uid = uid
|
||||||
|
cfg.username = username
|
||||||
|
cfg.displayname = displayname
|
||||||
|
cfg.email = email
|
||||||
|
cfg.created = int(time.time())
|
||||||
|
|
||||||
|
# Load the user model and set a temporary password
|
||||||
|
temporary_password = os.urandom(32).hex()
|
||||||
|
user = model_factory.user(uid)
|
||||||
|
user.set_password(temporary_password)
|
||||||
|
|
||||||
|
return user, temporary_password
|
Loading…
Reference in New Issue