PCv5/app/routes/admin/account.py

143 lines
5.4 KiB
Python

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 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/<user_id>/editer', methods=['GET', 'POST'])
@priv_required('access-admin-panel', 'edit-account')
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, "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, "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/<user_id>/supprimer', methods=['GET', 'POST'])
@priv_required('access-admin-panel', 'delete-account')
def adm_delete_account(user_id):
user = Member.query.filter_by(id=user_id).first_or_404()
# Note: A user deleting their own account will be disconnected.
# TODO: Add an overview of what will be deleted.
# * How many posts will be turned into guest posts
# * Option: purely delete the posts in question
# * How many PMs will be deleted (can't unassign PMs)
# * etc.
del_form = AdminDeleteAccountForm()
if del_form.submit.data:
if del_form.validate_on_submit():
user.delete()
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, del_form=del_form)