Clean up forms a bit and move auth forms to .auth

This commit is contained in:
Tim Van Baak 2020-04-25 10:07:42 -07:00
parent 1a289cb5c7
commit 768006ffbe
3 changed files with 222 additions and 209 deletions

View File

@ -15,7 +15,7 @@ from flask_login import (
LoginManager) LoginManager)
from amanuensis.config import RootConfigDirectoryContext from amanuensis.config import RootConfigDirectoryContext
from amanuensis.server.forms import LoginForm from amanuensis.server.auth.forms import LoginForm
from amanuensis.models import ModelFactory, AnonymousUserModel from amanuensis.models import ModelFactory, AnonymousUserModel
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -0,0 +1,17 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired
from amanuensis.server.forms import User
class LoginForm(FlaskForm):
"""/auth/login/"""
username = StringField(
'Username',
validators=[DataRequired(), User()])
password = PasswordField(
'Password',
validators=[DataRequired()])
remember = BooleanField('Stay logged in')
submit = SubmitField('Log in')

View File

@ -6,256 +6,252 @@ from wtforms import (
from wtforms.validators import DataRequired, ValidationError, Optional from wtforms.validators import DataRequired, ValidationError, Optional
from wtforms.widgets.html5 import NumberInput from wtforms.widgets.html5 import NumberInput
# from amanuensis.config import root
# from amanuensis.lexicon.manage import add_character
# from amanuensis.user import UserModel
from amanuensis.config import RootConfigDirectoryContext from amanuensis.config import RootConfigDirectoryContext
from amanuensis.lexicon import create_character_in_lexicon
# Custom validators # Custom validators
def user(exists=True): def User(should_exist: bool = True):
template = 'User "{{}}" {}'.format( template: str = 'User "{{}}" {}'.format(
"not found" if exists else "already exists") "not found" if should_exist else "already exists")
should_exist = bool(exists) should_exist_copy: bool = bool(should_exist)
def validate_user(form, field): def validate_user(form, field):
root: RootConfigDirectoryContext = current_app.config['root'] root: RootConfigDirectoryContext = current_app.config['root']
with root.user.read_index() as index: with root.user.read_index() as index:
if (field.data in index.keys()) != should_exist: if (field.data in index.keys()) != should_exist_copy:
raise ValidationError(template.format(field.data)) raise ValidationError(template.format(field.data))
return validate_user return validate_user
def lexicon(exists=True): def Lexicon(should_exist: bool = True):
template = 'Lexicon "{{}}" {}'.format( template: str = 'Lexicon "{{}}" {}'.format(
"not found" if exists else "already exists") "not found" if should_exist else "already exists")
should_exist = bool(exists) should_exist_copy: bool = bool(should_exist)
def validate_lexicon(form, field): def validate_lexicon(form, field):
root: RootConfigDirectoryContext = current_app.config['root'] root: RootConfigDirectoryContext = current_app.config['root']
with root.lexicon.read_index() as index: with root.lexicon.read_index() as index:
if (field.data in index.keys()) != should_exist: if (field.data in index.keys()) != should_exist_copy:
raise ValidationError(template.format(field.data)) raise ValidationError(template.format(field.data))
return validate_lexicon return validate_lexicon
# Forms # Forms
class LoginForm(FlaskForm):
"""/auth/login/"""
username = StringField('Username',
validators=[DataRequired(), user(exists=True)])
password = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Stay logged in')
submit = SubmitField('Log in')
class LexiconCreateForm(FlaskForm): class LexiconCreateForm(FlaskForm):
"""/admin/create/""" """/admin/create/"""
lexiconName = StringField( lexiconName = StringField(
'Lexicon name', 'Lexicon name',
validators=[DataRequired(), lexicon(exists=False)]) validators=[DataRequired(), Lexicon(should_exist=False)])
editorName = StringField( editorName = StringField(
'Username of editor', 'Username of editor',
validators=[DataRequired(), user(exists=True)]) validators=[DataRequired(), User(should_exist=True)])
promptText = TextAreaField("Prompt") promptText = TextAreaField('Prompt')
submit = SubmitField('Create') submit = SubmitField('Create')
# class LexiconConfigForm(FlaskForm): class LexiconConfigForm(FlaskForm):
# """/lexicon/<name>/session/settings/""" """/lexicon/<name>/session/settings/"""
# # General # General
# title = StringField('Title override', validators=[Optional()]) title = StringField('Title override', validators=[Optional()])
# editor = SelectField('Editor', validators=[DataRequired(), user(exists=True)]) editor = SelectField('Editor', validators=[DataRequired(), User(True)])
# prompt = TextAreaField('Prompt', validators=[DataRequired()]) prompt = TextAreaField('Prompt', validators=[DataRequired()])
# # Turn # Turn
# turnCurrent = IntegerField('Current turn', widget=NumberInput(), validators=[Optional()]) turnCurrent = IntegerField('Current turn', widget=NumberInput(), validators=[Optional()])
# turnMax = IntegerField('Number of turns', widget=NumberInput(), validators=[DataRequired()]) turnMax = IntegerField('Number of turns', widget=NumberInput(), validators=[DataRequired()])
# # Join # Join
# joinPublic = BooleanField("Show game on public pages") joinPublic = BooleanField("Show game on public pages")
# joinOpen = BooleanField("Allow players to join game") joinOpen = BooleanField("Allow players to join game")
# joinPassword = StringField("Password to join game", validators=[Optional()]) joinPassword = StringField("Password to join game", validators=[Optional()])
# joinMaxPlayers = IntegerField( joinMaxPlayers = IntegerField(
# "Maximum number of players", "Maximum number of players",
# widget=NumberInput(), widget=NumberInput(),
# validators=[DataRequired()]) validators=[DataRequired()])
# joinCharsPerPlayer = IntegerField( joinCharsPerPlayer = IntegerField(
# "Characters per player", "Characters per player",
# widget=NumberInput(), widget=NumberInput(),
# validators=[DataRequired()]) validators=[DataRequired()])
# # Publish # Publish
# publishNotifyEditorOnReady = BooleanField( publishNotifyEditorOnReady = BooleanField(
# "Notify the editor when a player marks an article as ready") "Notify the editor when a player marks an article as ready")
# publishNotifyPlayerOnReject = BooleanField( publishNotifyPlayerOnReject = BooleanField(
# "Notify a player when their article is rejected by the editor") "Notify a player when their article is rejected by the editor")
# publishNotifyPlayerOnAccept = BooleanField( publishNotifyPlayerOnAccept = BooleanField(
# "Notify a player when their article is accepted by the editor") "Notify a player when their article is accepted by the editor")
# publishDeadlines = StringField( publishDeadlines = StringField(
# "Turn deadline, as a crontab specification", validators=[Optional()]) "Turn deadline, as a crontab specification", validators=[Optional()])
# publishAsap = BooleanField( publishAsap = BooleanField(
# "Publish the turn immediately when the last article is accepted") "Publish the turn immediately when the last article is accepted")
# publishQuorum = IntegerField( publishQuorum = IntegerField(
# "Quorum to publish incomplete turn", widget=NumberInput(), validators=[Optional()]) "Quorum to publish incomplete turn", widget=NumberInput(), validators=[Optional()])
# publishBlockOnReady = BooleanField( publishBlockOnReady = BooleanField(
# "Block turn publish if any articles are awaiting editor review") "Block turn publish if any articles are awaiting editor review")
# # Article # Article
# articleIndexList = TextAreaField("Index specifications") articleIndexList = TextAreaField("Index specifications")
# articleIndexCapacity = IntegerField( articleIndexCapacity = IntegerField(
# "Index capacity override", widget=NumberInput(), validators=[Optional()]) "Index capacity override", widget=NumberInput(), validators=[Optional()])
# articleCitationAllowSelf = BooleanField( articleCitationAllowSelf = BooleanField(
# "Allow players to cite themselves") "Allow players to cite themselves")
# articleCitationMinExtant = IntegerField( articleCitationMinExtant = IntegerField(
# "Minimum number of extant articles to cite", widget=NumberInput(), validators=[Optional()]) "Minimum number of extant articles to cite", widget=NumberInput(), validators=[Optional()])
# articleCitationMaxExtant = IntegerField( articleCitationMaxExtant = IntegerField(
# "Maximum number of extant articles to cite", widget=NumberInput(), validators=[Optional()]) "Maximum number of extant articles to cite", widget=NumberInput(), validators=[Optional()])
# articleCitationMinPhantom = IntegerField( articleCitationMinPhantom = IntegerField(
# "Minimum number of phantom articles to cite", widget=NumberInput(), validators=[Optional()]) "Minimum number of phantom articles to cite", widget=NumberInput(), validators=[Optional()])
# articleCitationMaxPhantom = IntegerField( articleCitationMaxPhantom = IntegerField(
# "Maximum number of phantom articles to cite", widget=NumberInput(), validators=[Optional()]) "Maximum number of phantom articles to cite", widget=NumberInput(), validators=[Optional()])
# articleCitationMinTotal = IntegerField( articleCitationMinTotal = IntegerField(
# "Minimum number of articles to cite in total", widget=NumberInput(), validators=[Optional()]) "Minimum number of articles to cite in total", widget=NumberInput(), validators=[Optional()])
# articleCitationMaxTotal = IntegerField( articleCitationMaxTotal = IntegerField(
# "Maximum number of articles to cite in total", widget=NumberInput(), validators=[Optional()]) "Maximum number of articles to cite in total", widget=NumberInput(), validators=[Optional()])
# articleCitationMinChars = IntegerField( articleCitationMinChars = IntegerField(
# "Minimum number of characters to cite articles by", "Minimum number of characters to cite articles by",
# widget=NumberInput(), validators=[Optional()]) widget=NumberInput(), validators=[Optional()])
# articleCitationMaxChars = IntegerField( articleCitationMaxChars = IntegerField(
# "Maximum number of characters to cite articles by", "Maximum number of characters to cite articles by",
# widget=NumberInput(), validators=[Optional()]) widget=NumberInput(), validators=[Optional()])
# articleWordLimitSoft = IntegerField( articleWordLimitSoft = IntegerField(
# "Soft word limit", widget=NumberInput(), validators=[Optional()]) "Soft word limit", widget=NumberInput(), validators=[Optional()])
# articleWordLimitHard = IntegerField( articleWordLimitHard = IntegerField(
# "Hard word limit", widget=NumberInput(), validators=[Optional()]) "Hard word limit", widget=NumberInput(), validators=[Optional()])
# articleAddendumAllowed = BooleanField("Allow addendum articles") articleAddendumAllowed = BooleanField("Allow addendum articles")
# articleAddendumMax = IntegerField( articleAddendumMax = IntegerField(
# "Maximum number of addendum articles per character per turn", "Maximum number of addendum articles per character per turn",
# widget=NumberInput(), validators=[Optional()]) widget=NumberInput(), validators=[Optional()])
# # And finally, the submit button # And finally, the submit button
# submit = SubmitField("Submit") submit = SubmitField("Submit")
# def validate_publishDeadlines(form, field): def validate_publishDeadlines(form, field):
# if form.publishAsap.data: if form.publishAsap.data:
# raise ValidationError('Cannot specify deadline if immediate publishing is enabled') raise ValidationError('Cannot specify deadline if immediate publishing is enabled')
# # TODO add validators that call into extant valid check methods # TODO add validators that call into extant valid check methods
# def set_options(self, lexicon): # def set_options(self, lexicon):
# self.editor.choices = list(map(lambda x: (x, x), map( # self.editor.choices = list(map(lambda x: (x, x), map(
# lambda uid: UserModel.by(uid=uid).username, # lambda uid: UserModel.by(uid=uid).username,
# lexicon.join.joined))) # lexicon.join.joined)))
# def populate_from_lexicon(self, lexicon): # def populate_from_lexicon(self, lexicon):
# self.title.data = lexicon.title # self.title.data = lexicon.cfg.title
# self.editor.data = UserModel.by(uid=lexicon.editor).username # self.editor.data = ModelFactory(lexicon.ctx.root).user(lexicon.cfg.editor).cfg.username
# self.prompt.data = lexicon.prompt # self.prompt.data = lexicon.prompt
# self.turnCurrent.data = lexicon.turn.current # self.turnCurrent.data = lexicon.turn.current
# self.turnMax.data = lexicon.turn.max # self.turnMax.data = lexicon.turn.max
# self.joinPublic.data = lexicon.join.public # self.joinPublic.data = lexicon.join.public
# self.joinOpen.data = lexicon.join.open # self.joinOpen.data = lexicon.join.open
# self.joinPassword.data = lexicon.join.password # self.joinPassword.data = lexicon.join.password
# self.joinMaxPlayers.data = lexicon.join.max_players # self.joinMaxPlayers.data = lexicon.join.max_players
# self.joinCharsPerPlayer.data = lexicon.join.chars_per_player # self.joinCharsPerPlayer.data = lexicon.join.chars_per_player
# self.publishNotifyEditorOnReady.data = lexicon.publish.notify.editor_on_ready # self.publishNotifyEditorOnReady.data = lexicon.publish.notify.editor_on_ready
# self.publishNotifyPlayerOnReject.data = lexicon.publish.notify.player_on_reject # self.publishNotifyPlayerOnReject.data = lexicon.publish.notify.player_on_reject
# self.publishNotifyPlayerOnAccept.data = lexicon.publish.notify.player_on_accept # self.publishNotifyPlayerOnAccept.data = lexicon.publish.notify.player_on_accept
# self.publishDeadlines.data = lexicon.publish.deadlines # self.publishDeadlines.data = lexicon.publish.deadlines
# self.publishAsap.data = lexicon.publish.asap # self.publishAsap.data = lexicon.publish.asap
# self.publishQuorum.data = lexicon.publish.quorum # self.publishQuorum.data = lexicon.publish.quorum
# self.publishBlockOnReady.data = lexicon.publish.block_on_ready # self.publishBlockOnReady.data = lexicon.publish.block_on_ready
# self.articleIndexList.data = lexicon.article.index.list # self.articleIndexList.data = lexicon.article.index.list
# self.articleIndexCapacity.data = lexicon.article.index.capacity # self.articleIndexCapacity.data = lexicon.article.index.capacity
# self.articleCitationAllowSelf.data = lexicon.article.citation.allow_self # self.articleCitationAllowSelf.data = lexicon.article.citation.allow_self
# self.articleCitationMinExtant.data = lexicon.article.citation.min_extant # self.articleCitationMinExtant.data = lexicon.article.citation.min_extant
# self.articleCitationMaxExtant.data = lexicon.article.citation.max_extant # self.articleCitationMaxExtant.data = lexicon.article.citation.max_extant
# self.articleCitationMinPhantom.data = lexicon.article.citation.min_phantom # self.articleCitationMinPhantom.data = lexicon.article.citation.min_phantom
# self.articleCitationMaxPhantom.data = lexicon.article.citation.max_phantom # self.articleCitationMaxPhantom.data = lexicon.article.citation.max_phantom
# self.articleCitationMinTotal.data = lexicon.article.citation.min_total # self.articleCitationMinTotal.data = lexicon.article.citation.min_total
# self.articleCitationMaxTotal.data = lexicon.article.citation.max_total # self.articleCitationMaxTotal.data = lexicon.article.citation.max_total
# self.articleCitationMinChars.data = lexicon.article.citation.min_chars # self.articleCitationMinChars.data = lexicon.article.citation.min_chars
# self.articleCitationMaxChars.data = lexicon.article.citation.max_chars # self.articleCitationMaxChars.data = lexicon.article.citation.max_chars
# self.articleWordLimitSoft.data = lexicon.article.word_limit.soft # self.articleWordLimitSoft.data = lexicon.article.word_limit.soft
# self.articleWordLimitHard.data = lexicon.article.word_limit.hard # self.articleWordLimitHard.data = lexicon.article.word_limit.hard
# self.articleAddendumAllowed.data = lexicon.article.addendum.allowed # self.articleAddendumAllowed.data = lexicon.article.addendum.allowed
# self.articleAddendumMax.data = lexicon.article.addendum.max # self.articleAddendumMax.data = lexicon.article.addendum.max
# def update_lexicon(self, lexicon): # def update_lexicon(self, lexicon):
# with lexicon.edit() as l: # with lexicon.edit() as l:
# l.title = self.title.data # l.title = self.title.data
# l.editor = UserModel.by(name=self.editor.data).uid # l.editor = UserModel.by(name=self.editor.data).uid
# l.prompt = self.prompt.data # l.prompt = self.prompt.data
# l.turn.current = self.turnCurrent.data # l.turn.current = self.turnCurrent.data
# l.turn.max = self.turnMax.data # l.turn.max = self.turnMax.data
# l.join.public = self.joinPublic.data # l.join.public = self.joinPublic.data
# l.join.open = self.joinOpen.data # l.join.open = self.joinOpen.data
# l.join.password = self.joinPassword.data # l.join.password = self.joinPassword.data
# l.join.max_players = self.joinMaxPlayers.data # l.join.max_players = self.joinMaxPlayers.data
# l.join.chars_per_player = self.joinCharsPerPlayer.data # l.join.chars_per_player = self.joinCharsPerPlayer.data
# l.publish.notify.editor_on_ready = self.publishNotifyEditorOnReady.data # l.publish.notify.editor_on_ready = self.publishNotifyEditorOnReady.data
# l.publish.notify.player_on_reject = self.publishNotifyPlayerOnReject.data # l.publish.notify.player_on_reject = self.publishNotifyPlayerOnReject.data
# l.publish.notify.player_on_accept = self.publishNotifyPlayerOnAccept.data # l.publish.notify.player_on_accept = self.publishNotifyPlayerOnAccept.data
# l.publish.deadlines = self.publishDeadlines.data # l.publish.deadlines = self.publishDeadlines.data
# l.publish.asap = self.publishAsap.data # l.publish.asap = self.publishAsap.data
# l.publish.quorum = self.publishQuorum.data # l.publish.quorum = self.publishQuorum.data
# l.publish.block_on_ready = self.publishBlockOnReady.data # l.publish.block_on_ready = self.publishBlockOnReady.data
# l.article.index.list = self.articleIndexList.data # l.article.index.list = self.articleIndexList.data
# l.article.index.capacity = self.articleIndexCapacity.data # l.article.index.capacity = self.articleIndexCapacity.data
# l.article.citation.allow_self = self.articleCitationAllowSelf.data # l.article.citation.allow_self = self.articleCitationAllowSelf.data
# l.article.citation.min_extant = self.articleCitationMinExtant.data # l.article.citation.min_extant = self.articleCitationMinExtant.data
# l.article.citation.max_extant = self.articleCitationMaxExtant.data # l.article.citation.max_extant = self.articleCitationMaxExtant.data
# l.article.citation.min_phantom = self.articleCitationMinPhantom.data # l.article.citation.min_phantom = self.articleCitationMinPhantom.data
# l.article.citation.max_phantom = self.articleCitationMaxPhantom.data # l.article.citation.max_phantom = self.articleCitationMaxPhantom.data
# l.article.citation.min_total = self.articleCitationMinTotal.data # l.article.citation.min_total = self.articleCitationMinTotal.data
# l.article.citation.max_total = self.articleCitationMaxTotal.data # l.article.citation.max_total = self.articleCitationMaxTotal.data
# l.article.citation.min_chars = self.articleCitationMinChars.data # l.article.citation.min_chars = self.articleCitationMinChars.data
# l.article.citation.max_chars = self.articleCitationMaxChars.data # l.article.citation.max_chars = self.articleCitationMaxChars.data
# l.article.word_limit.soft = self.articleWordLimitSoft.data # l.article.word_limit.soft = self.articleWordLimitSoft.data
# l.article.word_limit.hard = self.articleWordLimitHard.data # l.article.word_limit.hard = self.articleWordLimitHard.data
# l.article.addendum.allowed = self.articleAddendumAllowed.data # l.article.addendum.allowed = self.articleAddendumAllowed.data
# l.article.addendum.max = self.articleAddendumMax.data # l.article.addendum.max = self.articleAddendumMax.data
# return True # return True
class LexiconJoinForm(FlaskForm): class LexiconJoinForm(FlaskForm):
"""/lexicon/<name>/join/""" """/lexicon/<name>/join/"""
password = StringField('Password') password = StringField('Password')
submit = SubmitField('Submit')
class LexiconCharacterForm(FlaskForm):
"""/lexicon/<name>/session/character/"""
characterName = StringField(
'Character name',
validators=[DataRequired()])
defaultSignature = TextAreaField('Default signature')
submit = SubmitField('Submit')
def for_new(self):
self.characterName.data = ""
self.defaultSignature.data = "~"
def for_character(self, lexicon, cid):
char = lexicon.cfg.character.get(cid)
self.characterName.data = char.name
self.defaultSignature.data = char.signature
def add_character(self, lexicon, user):
create_character_in_lexicon(user, lexicon, self.characterName.data)
# add_character(lexicon, user, {
# 'name': self.characterName.data,
# 'signature': self.defaultSignature.data,
# })
def update_character(self, lexicon, cid):
with lexicon.ctx.edit_config() as cfg:
char = cfg.character.get(cid)
char.name = self.characterName.data
char.signature = self.defaultSignature.data
class LexiconReviewForm(FlaskForm):
"""/lexicon/<name>/session/review/"""
APPROVED = 'Y'
REJECTED = 'N'
approved = RadioField(
'Buttons',
choices=((APPROVED, 'Approved'), (REJECTED, 'Rejected')))
submit = SubmitField("Submit") submit = SubmitField("Submit")
# class LexiconCharacterForm(FlaskForm): class LexiconPublishTurnForm(FlaskForm):
# """/lexicon/<name>/session/character/""" """/lexicon/<name>/session/"""
# characterName = StringField("Character name", validators=[DataRequired()]) submit = SubmitField('Publish turn')
# defaultSignature = TextAreaField("Default signature")
# submit = SubmitField("Submit")
# def for_new(self):
# self.characterName.data = ""
# self.defaultSignature.data = "~"
# def for_character(self, lexicon, cid):
# char = lexicon.character.get(cid)
# self.characterName.data = char.name
# self.defaultSignature.data = char.signature
# def add_character(self, lexicon, user):
# add_character(lexicon, user, {
# 'name': self.characterName.data,
# 'signature': self.defaultSignature.data,
# })
# def update_character(self, lexicon, cid):
# with lexicon.edit() as l:
# char = l.character.get(cid)
# char.name = self.characterName.data
# char.signature = self.defaultSignature.data
# class LexiconReviewForm(FlaskForm):
# """/lexicon/<name>/session/review/"""
# approved = RadioField("Buttons", choices=(("Y", "Approved"), ("N", "Rejected")))
# submit = SubmitField("Submit")
# class LexiconPublishTurnForm(FlaskForm):
# """/lexicon/<name>/session/"""
# submit = SubmitField("Publish turn")