from flask import flash, redirect, url_for, request from flask_login import current_user from wtforms import BooleanField from app.utils.priv_required import priv_required from app.models.user import Guest, Member from app.models.trophy import Trophy, Title from app.models.priv import Group from app.forms.account import AdminUpdateAccountForm, AdminDeleteAccountForm, \ AdminAccountEditTrophyForm, AdminAccountEditGroupForm from app.utils.render import render from app.utils.notify import notify from app import app, db from config import V5Config @app.route('/admin/compte//editer', methods=['GET', 'POST']) @priv_required('misc.admin-panel', 'edit.accounts') def adm_edit_account(user_id): user = Member.query.filter_by(id=user_id).first_or_404() form = AdminUpdateAccountForm(prefix="user") class TrophyForm(AdminAccountEditTrophyForm): pass class GroupForm(AdminAccountEditGroupForm): pass for t in Trophy.query.all(): setattr(TrophyForm, f't{t.id}', BooleanField(t.name)) setattr(TrophyForm, "trophies", {f't{t.id}': t for t in Trophy.query.all()}) setattr(TrophyForm, "user_trophies", [f't{t.id}' for t in user.trophies]) trophy_form = TrophyForm(prefix="trophies") for g in Group.query.all(): setattr(GroupForm, f'g{g.id}', BooleanField(g.name)) setattr(GroupForm, "groups", {f'g{g.id}': g for g in Group.query.all()}) setattr(GroupForm, "user_groups", [f'g{g.id}' for g in user.groups]) group_form = GroupForm(prefix="group") titles = [(t.id, t.name) for t in Title.query.all()] titles.insert(0, (-1, "Membre")) form.title.choices = titles if form.submit.data: if form.validate_on_submit(): newname = form.username.data names = list(Member.query.filter(Member.id != user.id).values(Member.name)) if newname in names: # TODO: avoid this exception # You cannot user vd.name_available because name will always be # invalid! Maybe you can add another validator with arguments raise Exception(f'{newname} is not available') user.update( avatar=form.avatar.data or None, name=form.username.data or None, email=form.email.data or None, email_confirmed=form.email_confirmed.data, password=form.password.data or None, birthday=form.birthday.data, signature=form.signature.data, title=form.title.data, bio=form.biography.data, newsletter=form.newsletter.data, xp=form.xp.data or None, ) db.session.merge(user) db.session.commit() # TODO: send an email to member saying his account has been modified user.notify(f"Vos informations personnelles ont été modifiées par {current_user.name}.") flash('Modifications effectuées', 'ok') return redirect(request.url) else: flash('Erreur lors de la modification', 'error') # Trophies if trophy_form.submit.data: if trophy_form.validate_on_submit(): for id, field in trophy_form.__dict__.items(): if id[0] == "t": if field.data: user.add_trophy(int(id[1:])) else: user.del_trophy(int(id[1:])) db.session.merge(user) db.session.commit() flash('Modifications effectuées', 'ok') return redirect(request.url) else: flash("Erreur lors de la modification des trophées", 'error') # Groups if group_form.submit.data: if group_form.validate_on_submit(): for id, field in group_form.__dict__.items(): if id[0] == "g": if field.data: user.add_group(int(id[1:])) else: user.del_group(int(id[1:])) db.session.merge(user) db.session.commit() flash('Modifications effectuées', 'ok') return redirect(request.url) else: flash("Erreur lors de la modification des groupes", 'error') trophies_owned = set() for t in user.trophies: trophies_owned.add(f"t{t.id}") groups_owned = set() for g in user.groups: groups_owned.add(f"g{g.id}") return render('admin/edit_account.html', scripts=["+scripts/entropy.js"], user=user, form=form, trophy_form=trophy_form, trophies_owned=trophies_owned, group_form=group_form, groups_owned=groups_owned) @app.route('/admin/compte//supprimer', methods=['GET', 'POST']) @priv_required('misc.admin-panel', 'delete.accounts') def adm_delete_account(user_id): # A user deleting their own account will be disconnected user = Member.query.filter_by(id=user_id).first_or_404() # TODO: Number of comments by *other* members which will be deleted stats = { 'comments': len(user.comments()), 'topics': len(user.topics()), 'programs': len(user.programs()), 'groups': len(user.groups), 'privs': len(user.special_privileges()), } del_form = AdminDeleteAccountForm() if del_form.submit.data: if del_form.validate_on_submit(): if del_form.transfer.data: guest = Guest(user.generate_guest_name()) db.session.add(guest) db.session.commit() user.transfer_posts(guest) db.session.commit() else: user.delete_posts() db.session.commit() user.delete() db.session.commit() flash('Compte supprimé', 'ok') return redirect(url_for('adm')) else: flash('Erreur lors de la suppression du compte', 'error') del_form.delete.data = False # Force to tick to delete the account return render('admin/delete_account.html', user=user, stats=stats, del_form=del_form)