Add user creation backend logic
This commit is contained in:
parent
1926bee2a4
commit
6eadb5162a
|
@ -0,0 +1,45 @@
|
||||||
|
"""
|
||||||
|
User query interface
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from amanuensis.db import DbContext, User
|
||||||
|
from amanuensis.errors import ArgumentError
|
||||||
|
|
||||||
|
|
||||||
|
def create_user(
|
||||||
|
db: DbContext,
|
||||||
|
username: str,
|
||||||
|
password: str,
|
||||||
|
display_name: str,
|
||||||
|
email: str,
|
||||||
|
is_site_admin: bool) -> User:
|
||||||
|
"""
|
||||||
|
Create a new user.
|
||||||
|
"""
|
||||||
|
# Verify username
|
||||||
|
if len(username) < 3 or len(username) > 32:
|
||||||
|
raise ArgumentError('Username must be between 3 and 32 characters')
|
||||||
|
if re.match(r'^[0-9-_]*$', username):
|
||||||
|
raise ArgumentError('Username must contain a letter')
|
||||||
|
if not re.match(r'^[A-Za-z0-9-_]*$', username):
|
||||||
|
raise ArgumentError('Username may only contain alphanumerics, dash, and underscore')
|
||||||
|
# Verify password
|
||||||
|
if not password:
|
||||||
|
raise ArgumentError('Password must be provided')
|
||||||
|
# If display name is not provided, use the username
|
||||||
|
if not display_name.strip():
|
||||||
|
display_name = username
|
||||||
|
|
||||||
|
new_user = User(
|
||||||
|
username=username,
|
||||||
|
password=password,
|
||||||
|
display_name=display_name,
|
||||||
|
email=email,
|
||||||
|
is_site_admin=is_site_admin,
|
||||||
|
)
|
||||||
|
db.session.add(new_user)
|
||||||
|
db.session.commit()
|
||||||
|
return new_user
|
|
@ -1,32 +1,10 @@
|
||||||
|
"""
|
||||||
|
Submodule of custom exception types
|
||||||
|
"""
|
||||||
|
|
||||||
class AmanuensisError(Exception):
|
class AmanuensisError(Exception):
|
||||||
"""Base class for exceptions in amanuensis"""
|
"""Base class for exceptions in amanuensis"""
|
||||||
|
|
||||||
|
|
||||||
class MissingConfigError(AmanuensisError):
|
|
||||||
"""A config file is missing that was expected to be present"""
|
|
||||||
def __init__(self, path):
|
|
||||||
super().__init__("A config file or directory was expected to "
|
|
||||||
f"exist, but could not be found: {path}")
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigAlreadyExistsError(AmanuensisError):
|
|
||||||
"""Attempted to create a config, but it already exists"""
|
|
||||||
def __init__(self, path):
|
|
||||||
super().__init__("Attempted to create a config, but it already "
|
|
||||||
f"exists: {path}")
|
|
||||||
|
|
||||||
|
|
||||||
class MalformedConfigError(AmanuensisError):
|
|
||||||
"""A config file could not be read and parsed"""
|
|
||||||
|
|
||||||
|
|
||||||
class ReadOnlyError(AmanuensisError):
|
|
||||||
"""A config was edited in readonly mode"""
|
|
||||||
|
|
||||||
|
|
||||||
class ArgumentError(AmanuensisError):
|
class ArgumentError(AmanuensisError):
|
||||||
"""An internal call was made with invalid arguments"""
|
"""An internal call was made with invalid arguments"""
|
||||||
|
|
||||||
|
|
||||||
class IndexMismatchError(AmanuensisError):
|
|
||||||
"""An id was obtained from an index, but the object doesn't exist"""
|
|
||||||
|
|
|
@ -2,23 +2,47 @@ import pytest
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
|
||||||
from amanuensis.db import *
|
from amanuensis.db import *
|
||||||
|
import amanuensis.backend.user as userq
|
||||||
|
from amanuensis.errors import ArgumentError
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def session():
|
def db():
|
||||||
db = DbContext('sqlite:///:memory:', debug=True)
|
db = DbContext('sqlite:///:memory:', debug=True)
|
||||||
db.create_all()
|
db.create_all()
|
||||||
return db.session
|
return db
|
||||||
|
|
||||||
|
|
||||||
def test_create(session):
|
def test_create(db):
|
||||||
"""Simple test that the database creates fine from scratch."""
|
"""Simple test that the database creates fine from scratch."""
|
||||||
assert session.query(func.count(User.id)).scalar() == 0
|
assert db.session.query(func.count(User.id)).scalar() == 0
|
||||||
assert session.query(func.count(Lexicon.id)).scalar() == 0
|
assert db.session.query(func.count(Lexicon.id)).scalar() == 0
|
||||||
assert session.query(func.count(Membership.id)).scalar() == 0
|
assert db.session.query(func.count(Membership.id)).scalar() == 0
|
||||||
assert session.query(func.count(Character.id)).scalar() == 0
|
assert db.session.query(func.count(Character.id)).scalar() == 0
|
||||||
assert session.query(func.count(Article.id)).scalar() == 0
|
assert db.session.query(func.count(Article.id)).scalar() == 0
|
||||||
assert session.query(func.count(ArticleIndex.id)).scalar() == 0
|
assert db.session.query(func.count(ArticleIndex.id)).scalar() == 0
|
||||||
assert session.query(func.count(ArticleIndexRule.id)).scalar() == 0
|
assert db.session.query(func.count(ArticleIndexRule.id)).scalar() == 0
|
||||||
assert session.query(func.count(ArticleContentRule.id)).scalar() == 0
|
assert db.session.query(func.count(ArticleContentRule.id)).scalar() == 0
|
||||||
assert session.query(func.count(Post.id)).scalar() == 0
|
assert db.session.query(func.count(Post.id)).scalar() == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_user(db):
|
||||||
|
"""New user creation"""
|
||||||
|
kwargs = {
|
||||||
|
'username': 'username',
|
||||||
|
'password': 'password',
|
||||||
|
'display_name': 'User Name',
|
||||||
|
'email': 'user@example.com',
|
||||||
|
'is_site_admin': False
|
||||||
|
}
|
||||||
|
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
userq.create_user(db, **{**kwargs, 'username': 'user name'})
|
||||||
|
|
||||||
|
with pytest.raises(ArgumentError):
|
||||||
|
userq.create_user(db, **{**kwargs, 'password': None})
|
||||||
|
|
||||||
|
new_user = userq.create_user(db, **kwargs)
|
||||||
|
assert new_user
|
||||||
|
assert new_user.id is not None
|
||||||
|
assert new_user.created is not None
|
||||||
|
|
Loading…
Reference in New Issue