def npc_visibility(npcid: int, campaignid: int): if not current_user.is_authenticated: abort(403) npc = NPC.query.get(npcid) if npc is None: abort(404) if npc.campaign.id != campaignid: abort(404) if current_user.profile != npc.campaign.user: abort(403) if request.method == 'POST': data = request.get_json() assert data is not None logger.debug(data) if data['visibility']: logger.debug(f"Showing NPC {npc.character.title}") npc.visible = True else: logger.debug(f"Hiding NPC {npc.character.title}") npc.visible = False session.commit() logger.debug(data) response = { 'npc': npcid, 'campaign': campaignid, 'visibility': npc.visible } return jsonify(response)
def delete_folder(id=None): deletefolderform = DeleteAssetFolderForm(prefix="deletefolderform") folder = AssetFolder.query.get(id) if not folder.owner == current_user.profile: logger.debug("Not deleting folder for other person") abort(403) if folder.parent is None: logger.debug("Can't delete top folder") abort(403) if deletefolderform.validate_on_submit(): logger.debug("Delete an empty folder") parent_id = folder.parent.id if str(folder.id) != deletefolderform.id.data: logger.debug(f"Wrong ids specified {folder.id} " f"and {deletefolderform.id.data}") abort(403) if folder.files: logger.debug("Folder contains files") abort(403) session.delete(folder) session.commit() return redirect(url_for('userassets.index', folder_id=parent_id)) return redirect(url_for('userassets.index', folder_id=id))
def editjson(id: int): """Lets the user edit the raw json of the character.""" c = get_character(id, check_author=True) form = ImportForm(obj=c) if form.validate_on_submit(): assert form.body.data is not None c.title = form.title.data c.body = form.body.data if form.migration.data: logger.debug("Trying to migrate data") data = form.body.data c.body = migrate(data, latest, migrations=migrations) elif form.conversion.data: logger.debug("Conversion is checked") data = form.body.data c.body = convert_from_dholes(data) logentry = LogEntry(c, "JSON edited", user_id=current_user.id) session.add(logentry) session.commit() return redirect(url_for('character.view', id=c.id)) form.submit.label.text = 'Save' validation_errors = c.validate() return render_template('character/import.html.jinja', title="Edit JSON", validation_errors=validation_errors, form=form, type=None)
def update(id: int): character = get_character(id, check_author=True) if request.method == "POST": update = request.get_json() assert update is not None for setting in update: character.set_attribute(setting) field = setting['field'] subfield = setting.get('subfield', '') value = setting['value'] type = setting.get('type', 'value') if type == 'portrait' and value is not None: value = "[image]" log_subfield = '' if subfield is not None and subfield != 'None': log_subfield = ' ' + subfield log_message = (f"set {type} on {field}{log_subfield}: {value}") logentry = LogEntry(character, log_message, user_id=current_user.id) session.add(logentry) character.store_data() session.commit() return "OK"
def api_invite_delete(id): invite = Invite.query.get(id) if current_user.profile.id != invite.owner_id: abort(403) session.delete(invite) session.commit() return jsonify({'html': 'Deleted'})
def create(): form = CreateForm() if form.validate_on_submit(): c = Campaign(title=form.title.data, user_id=current_user.profile.id) session.add(c) session.commit() return redirect(url_for('campaign.view', id=c.id)) return render_template('campaign/create.html.jinja', form=form)
def folder(id: int): c = get_character(id, check_author=True) form = ChooseFolderForm() if form.validate_on_submit(): c.folder = form.folder_id.data # type: ignore session.commit() return render_template('character/move_to_folder.html.jinja', form=form, character=c)
def create_folder(folder_id=None): folderform = NewFolderForm(prefix="newfolderform") if folderform.validate_on_submit(): logger.debug("Create a new folder") folder = AssetFolder(parent_id=folderform.parent_id.data, title=folderform.title.data, owner=current_user.profile) session.add(folder) session.commit() return redirect(url_for('userassets.index', folder_id=folder_id))
def delete(fileid, filename): logger.debug("Delete asset") asset = Asset.query.get(fileid) form = DeleteAssetForm(prefix="deleteasset") if form.validate_on_submit(): if asset.owner != current_user.profile: abort(403) flash("You just deleted an asset") session.delete(asset) session.commit() return redirect(url_for('userassets.index', folder_id=asset.folder_id))
def folders(folder_id=None): new_folder_form = NewFolderForm(prefix='new_folder') if new_folder_form.validate_on_submit(): print("From validated, add folder") folder = Folder() new_folder_form.populate_obj(folder) session.add(folder) session.commit() return redirect('/content') else: print("Form did not validate") # return redirect(request.url) new_folder_form.owner_id.data = current_user.profile.id new_folder_form.parent_id.data = folder_id current_folder = Folder.query.get(folder_id) folders = None characters = None campaigns = None tree = [] if current_folder is None: folders = current_user.profile.folders.filter( Folder.parent_id.__eq__(None)) characters = current_user.profile.characters.filter( Character.folder_id.__eq__(None)) campaigns = current_user.profile.campaigns.filter( campaignmodels.Campaign.folder_id.__eq__(None)) else: folders = current_folder.subfolders characters = current_folder.characters campaigns = current_folder.campaigns f = current_folder while f.parent: tree.append(f.parent) f = f.parent tree.reverse() data = { 'current_folder': current_folder, 'tree': tree, 'folders': folders, 'characters': characters, 'campaigns': campaigns } return render_template('content/folders.html.jinja', new_folder_form=new_folder_form, data=data)
def reset_password(token: str): if current_user.is_authenticated: return redirect(url_for('main.index')) user = User.verify_reset_password_token(token) form = ResetPasswordForm() if form.validate_on_submit(): if user is not None: user.set_password(form.password.data) session.commit() flash('Your password has been reset.') return redirect(url_for('auth.login')) return render_template('auth/reset_password.html.jinja', form=form)
def register(): if current_user.is_authenticated: return redirect(url_for('main.index')) form = RegistrationForm() if form.validate_on_submit(): user = User(username=form.username.data, email=form.email.data) user.set_password(form.password.data) session.add(user) session.commit() flash('Congratulations, you are now a registered user!') return redirect(url_for('auth.login')) return render_template('auth/register.html.jinja', title='Register', form=form)
def remove_player(id: int, playerid: int): form = RemovePlayerForm() c = Campaign.query.get(id) player = UserProfile.query.get(playerid) if form.validate_on_submit(): c.players.remove(player) session.commit() return redirect(url_for('campaign.view', id=c.id)) form.id.data = c.id form.player.data = player.id return render_template('campaign/removeplayer.html.jinja', player=player, campaign=c, form=form)
def index(): user_profile = UserProfile.query.get(current_user.id) if user_profile is None: user_profile = UserProfile(user_id=current_user.id) session.add(user_profile) session.commit() logger.info(f"Showing profile {user_profile.id}") characters = user_profile.characters folders = user_profile.folders # .filter(Folder.parent_id.__eq__(None)) return render_template('profile/profile.html.jinja', profile=user_profile, characters=characters, folders=folders)
def view(id, character, editable): subskillform = SubskillForm(prefix="subskillform") if editable and subskillform.data and subskillform.validate_on_submit(): character.add_subskill(subskillform.name.data, subskillform.parent.data) logentry = LogEntry(character, f"add subskill {subskillform.name.data} " + f"under {subskillform.parent.data}", user_id=current_user.id) session.add(logentry) character.store_data() session.commit() return redirect(url_for('character.view', id=id)) skillform = SkillForm(prefix="skillform") if editable and skillform.data and skillform.validate_on_submit(): skills = character.skills() for skill in skills: if skillform.name.data == skill['name']: flash("Skill already exists") return redirect(url_for('character.view', id=id)) character.add_skill(skillform.name.data) character.store_data() logentry = LogEntry(character, f"add skill {subskillform.name.data}", user_id=current_user.id) session.add(logentry) session.commit() return redirect(url_for('character.view', id=id)) typeheader = "1920s Era Investigator" if character.game and character.game[1] == "Modern": typeheader = "Modern Era" shared = Invite.query_for(character).count() return render_template('character/coc7e/sheet.html.jinja', shared=shared, character=character, typeheader=typeheader, editable=editable, skillform=skillform, subskillform=subskillform)
def remove_npc(id: int, characterid: int): npc = NPC.query.get(characterid) form = RemoveCharacterForm() if form.validate_on_submit(): if npc.campaign.id == id: session.delete(npc) session.commit() return redirect(url_for('campaign.view', id=id)) form.id.data = npc.campaign.id form.character.data = npc.character.id return render_template('campaign/removecharacter.html.jinja', character=npc.character, campaign=npc.campaign, form=form)
def move(fileid, filename): asset = Asset.query.get(fileid) redirect_id = asset.folder.id form = MoveAssetForm(prefix="moveasset") if form.validate_on_submit(): if asset.owner != current_user.profile: abort(403) destinationfolder = form.folder.data if destinationfolder is not None: logger.debug(f"Move {asset.system_path} " f"to {destinationfolder.system_path}") os.replace(asset.system_path, destinationfolder.system_path / asset.filename) asset.folder = destinationfolder session.commit() flash("You moved your file") return redirect(url_for('userassets.index', folder_id=redirect_id))
def delete(id: int): """Delete a character.""" character = get_character(id, check_author=True) if current_user.profile.id != character.user_id: abort(404) form = DeleteForm() if form.validate_on_submit(): session.delete(character) session.commit() return redirect(url_for('character.index')) form.character_id.data = character.id return render_template('character/delete_character.html.jinja', form=form, character=character)
def manage_npc(id: int, npcid: int): npc = NPC.query.get(npcid) transferform = NPCTransferForm(prefix="npctransfer", npc_id=npcid) if npc is None: return abort(404) if npc.campaign_id != id: return abort(404) if current_user.profile != npc.campaign.user: return abort(404) if transferform.submit.data: if transferform.validate_on_submit(): player = UserProfile.query.get(transferform.player.data) campaign = npc.campaign # Create a copy of the character new_character = Character(title=npc.character.title, body=npc.character.body, user_id=player.id) session.add(new_character) # Add the character to the campaign campaign.characters.append(new_character) # Remove the NPC session.delete(npc) # Commit changes session.commit() return redirect(url_for('campaign.view', id=campaign.id)) transferform.player.choices = [(p.id, p.user.username) for p in npc.campaign.players] return render_template('campaign/managenpc.html.jinja', npc=npc, transferform=transferform)
def remove_character(id: int, characterid: int): c = Campaign.query.get(id) char = Character.query.get(characterid) if current_user.profile.id != c.user_id \ and char.user_id != current_user.profile.id: abort(404) form = RemoveCharacterForm() if form.validate_on_submit(): c.characters.remove(char) session.commit() return redirect(url_for('campaign.view', id=c.id)) form.id.data = c.id form.character.data = char.id return render_template('campaign/removecharacter.html.jinja', character=char, campaign=c, form=form)
def create(chartype: str): character_module = globals()[chartype] if chartype in globals() else core form = getattr(character_module, 'CreateForm', CreateForm)() template = getattr(character_module, 'CREATE_TEMPLATE', 'character/create.html.jinja') if form.validate_on_submit(): logger.debug(f"Creating new character specified by {form.data}") char_data = character_module.new_character(**form.data) c = Character(title=form.title.data, body=char_data, user_id=current_user.profile.id) session.add(c) session.commit() return redirect(url_for('character.view', id=c.id)) form.system.data = chartype return render_template(template, form=form, type=type)
def import_character(type=None, id: int = None, code: str = None): logger.debug(f"{type}, {code}, {id}") character = None if id: character = get_character(id, check_author=True) elif code is not None: invite = Invite.query.get(code) if invite is None or invite.table != Character.__tablename__: return "Invalid code" character = Character.query.get(invite.object_id) form = ImportForm(obj=character) if form.validate_on_submit(): c = Character(title=form.title.data, body=form.body.data, user_id=current_user.profile.id) session.add(c) session.commit() return redirect(url_for('character.view', id=c.id)) return render_template('character/import.html.jinja', form=form, type=None)
def handout_players(campaignid: int, handoutid: int): if not current_user.is_authenticated: abort(403) handout = Handout.query.get(handoutid) if handout is None: abort(404) if handout.campaign.id != campaignid: abort(404) if current_user.profile != handout.campaign.user: abort(403) if request.method == 'POST': data = request.get_json() assert data is not None player = handout.campaign.players_by_id.get(data['player_id'], None) if player is not None: if data['state']: if player not in handout.players: logger.debug(f"Adding player {player} to {handout}") handout.players.append(player) else: if player in handout.players: logger.debug(f"Removing player {player} to {handout}") handout.players.remove(player) session.commit() logger.debug(data) response = { 'players': { p.user.username: p in handout.players for p in handout.campaign.players } } return jsonify(response)
def upload_file(folder_id=None): form = UploadForm(prefix='fileupload') if form.validate_on_submit(): fileobject = form.uploaded.data folder: AssetFolder = AssetFolder.query.get(form.folder_id.data) if folder.owner != current_user.profile: abort(403) if fileobject.filename: filename = secure_filename(fileobject.filename) folder.system_path.mkdir(parents=True, exist_ok=True) fileobject.save(folder.system_path / filename) asset = Asset(filename=fileobject.filename, folder=folder, owner=current_user.profile) session.add(asset) session.commit() return redirect(url_for('userassets.index', folder_id=folder_id))
def edit(id: int): c = Campaign.query.get(id) form = EditForm(obj=c, prefix="campaign_edit") folderform = ChooseFolderForm(prefix="choose_folder") if form.submit.data and form.validate_on_submit(): form.populate_obj(c) session.add(c) session.commit() return redirect(url_for('campaign.view', id=c.id)) if folderform.choose.data and folderform.validate_on_submit(): print("Folder form submitted!") c.folder = folderform.folder_id.data session.commit() return redirect(url_for('campaign.view', id=c.id)) folderform.folder_id.data = c.folder return render_template('campaign/edit.html.jinja', form=form, folderform=folderform)
def share(id: int): """Share a character.""" character = get_character(id, check_author=True) logger.debug("Finding previous invite") invite = Invite.query_for(character).first() logger.debug(f"Invites found {invite}") if not invite: logger.debug(f"Creating an invite for character {character.id}") invite = Invite(character) invite.owner_id = character.user_id session.add(invite) session.commit() share_url = url_for('character.shared', code=invite.id, _external=True) form = None html_response = render_template('character/api_share.html.jinja', form=form, url=share_url, code=invite.id) return jsonify({'url': share_url, 'html': html_response})
def invite_delete(id): invite = Invite.query.get(id) if current_user.profile.id != invite.owner_id: logger.debug("Wrong user") abort(403) form = DeleteInviteForm() if form.validate_on_submit(): logger.debug("Delete form validated") session.delete(invite) session.commit() return redirect('/') objclass = get_class_by_tablename(invite.table) obj = None if objclass is not None: obj = objclass.query.get(invite.object_id) form.id.data = invite.id return render_template('main/invite_delete.html.jinja', obj=obj, invite=invite, form=form)
def index(folder_id=None): if current_user.profile.assetfolders.count() < 1: logger.debug("Creating initial folder") rootfolder = AssetFolder(title='assets', owner=current_user.profile) session.add(rootfolder) session.commit() if folder_id is not None: folder = AssetFolder.query.get(folder_id) else: folder = current_user.profile.assetfolders \ .filter(AssetFolder.parent_id.__eq__(None)).first() form = UploadForm(folder_id=folder.id, prefix="fileupload") folderform = NewFolderForm(parent_id=folder.id, prefix="newfolderform") deletefolderform = DeleteAssetFolderForm(id=folder.id, prefix="deletefolderform") return render_template('userassets/assets.html.jinja', form=form, folderform=folderform, deletefolderform=deletefolderform, folder=folder)
def message_player(campaign_id: int, player_id: int = None): c = Campaign.query.get(campaign_id) player = None if player_id: player = UserProfile.query.get(player_id) form = MessagePlayerForm() if form.validate_on_submit(): flash(form.message.data) logger.debug(request.form) message = Message() form.populate_obj(message) if not form.to_id.data: message.to_id = None # type: ignore session.add(message) session.commit() return redirect(url_for('campaign.view', id=c.id)) form.campaign_id.data = c.id form.to_id.data = player_id form.from_id.data = c.user_id messages = c.messages.filter( or_( and_(Message.to_id == player_id, Message.from_id == current_user.profile.id), and_(Message.to_id == current_user.profile.id, Message.from_id == player_id))) return render_template('campaign/message_player.html.jinja', player=player, campaign=c, form=form, messages=messages)
def join(code: str): inv = Invite.query.get(code) if inv is None or inv.table != Campaign.__tablename__: return "Invalid code" joinform = JoinCampaignForm() if joinform.validate_on_submit(): campaign = Campaign.query.get(inv.object_id) player = current_user.profile if player not in campaign.players: campaign.players.append(player) session.commit() return redirect(url_for('campaign.view', id=campaign.id)) flash("Valid code") campaign = Campaign.query.get(inv.object_id) joinform = JoinCampaignForm(invite_code=code) return render_template('campaign/joincampaign.html.jinja', campaign=campaign, joinform=joinform)