diff --git a/amanuensis/lexicon/setup.py b/amanuensis/lexicon/setup.py index 06d3b8c..22c738b 100644 --- a/amanuensis/lexicon/setup.py +++ b/amanuensis/lexicon/setup.py @@ -95,7 +95,7 @@ def player_can_create_character( def create_character_in_lexicon( player: UserModel, lexicon: LexiconModel, - name: str) -> None: + name: str) -> str: """ Unconditionally creates a character for a player """ @@ -129,3 +129,5 @@ def create_character_in_lexicon( # Log addition lexicon.log(f'Character "{name}" created ({character.cid})') + + return character.cid diff --git a/amanuensis/server/session/__init__.py b/amanuensis/server/session/__init__.py index 1dfc029..f9e873a 100644 --- a/amanuensis/server/session/__init__.py +++ b/amanuensis/server/session/__init__.py @@ -9,7 +9,10 @@ from flask import ( Markup) from flask_login import current_user -from amanuensis.lexicon import attempt_publish +from amanuensis.lexicon import ( + attempt_publish, + get_player_characters, + create_character_in_lexicon) from amanuensis.models import LexiconModel from amanuensis.parser import ( parse_raw_markdown, @@ -57,34 +60,52 @@ def session(name): characters=characters) -def edit_character(name, form, cid): - if form.validate_on_submit(): - # Update character - form.update_character(g.lexicon, cid) - flash('Character updated') +def edit_character(name, form, character): + if not form.is_submitted(): + # GET, populate with values + return render_template( + 'session.character.jinja', form=form.for_character(character)) + + if not form.validate(): + # POST with invalid data, return unchanged + return render_template('session.character.jinja', form=form) + + # POST with valid data, update character + with g.lexicon.ctx.edit_config() as cfg: + char = cfg.character[character.cid] + char.name = form.characterName.data + char.signature = form.defaultSignature.data + flash('Character updated') + return redirect(url_for('session.session', name=name)) + + +def create_character(name: str, form: LexiconCharacterForm): + # Characters can't be created if the game has already started + if g.lexicon.status != LexiconModel.PREGAME: + flash("Characters can't be added after the game has started") + return redirect(url_for('session.session', name=name)) + # Characters can't be created beyond the per-player limit + player_characters = get_player_characters(g.lexicon, current_user.uid) + if len(list(player_characters)) >= g.lexicon.cfg.join.chars_per_player: + flash("Can't create more characters") return redirect(url_for('session.session', name=name)) if not form.is_submitted(): - # On GET, populate with the character - form.for_character(g.lexicon, cid) - return render_template('session.character.jinja', form=form, action='edit') + # GET, populate with default values + return render_template( + 'session.character.jinja', form=form.for_new()) + if not form.validate(): + # POST with invalid data, return unchanged + return render_template('session.character.jinja', form=form) -def create_character(name, form): - if form.validate_on_submit(): - # On POST, verify character can be added - if not g.lexicon.can_add_character(current_user.uid): - flash('Operation not permitted') - return redirect(url_for('session.session', name=name)) - # Add the character - form.add_character(g.lexicon, current_user) - flash('Character created') - return redirect(url_for('session.session', name=name)) - - if not form.is_submitted(): - # On GET, populate form for new character - form.for_new() - return render_template('session.character.jinja', form=form, action='create') + # POST with valid data, create character + char_name = form.characterName.data + cid = create_character_in_lexicon(current_user, g.lexicon, char_name) + with g.lexicon.ctx.edit_config() as cfg: + cfg.character[cid].signature = form.defaultSignature.data + flash('Character created') + return redirect(url_for('session.session', name=name)) @bp_session.route('/character/', methods=['GET', 'POST']) @@ -93,16 +114,21 @@ def create_character(name, form): def character(name): form = LexiconCharacterForm() cid = request.args.get('cid') - if cid: - if cid not in g.lexicon.cfg.character: - flash('Character not found') - return redirect(url_for('session.session', name=name)) - if (g.lexicon.cfg.character.get(cid).player != current_user.uid - and g.lexicon.cfg.editor != current_user.uid): - flash('Access denied') - return redirect(url_for('session.session', name=name)) - return edit_character(name, form, cid) - return create_character(name, form) + if not cid: + # No character specified, creating a new character + return create_character(name, form) + + character = g.lexicon.cfg.character.get(cid) + if not character: + # Bad character id, abort + flash('Character not found') + return redirect(url_for('session.session', name=name)) + if current_user.uid not in (character.player, g.lexicon.cfg.editor): + # Only its owner and the editor can edit a character + flash('Access denied') + return redirect(url_for('session.session', name=name)) + # Edit allowed + return edit_character(name, form, character) @bp_session.route('/settings/', methods=['GET', 'POST']) diff --git a/amanuensis/server/session/forms.py b/amanuensis/server/session/forms.py index 46a7b55..9dee59c 100644 --- a/amanuensis/server/session/forms.py +++ b/amanuensis/server/session/forms.py @@ -3,8 +3,6 @@ from wtforms import ( StringField, SubmitField, TextAreaField, RadioField) from wtforms.validators import DataRequired -from amanuensis.lexicon import create_character_in_lexicon - class LexiconCharacterForm(FlaskForm): """/lexicon//session/character/""" @@ -17,24 +15,12 @@ class LexiconCharacterForm(FlaskForm): def for_new(self): self.characterName.data = "" self.defaultSignature.data = "~" + return self - 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 + def for_character(self, character): + self.characterName.data = character.name + self.defaultSignature.data = character.signature + return self class LexiconReviewForm(FlaskForm): diff --git a/amanuensis/server/session/session.character.jinja b/amanuensis/server/session/session.character.jinja index f96946d..81b3036 100644 --- a/amanuensis/server/session/session.character.jinja +++ b/amanuensis/server/session/session.character.jinja @@ -9,6 +9,9 @@

{{ form.characterName.label }}
{{ form.characterName(size=32) }}

+ {% for error in form.characterName.errors %} + {{ error }}
+ {% endfor %}

{{ form.defaultSignature.label }}
{{ form.defaultSignature(class_='fullwidth') }}