logging: add some logging for v5 events
parent
e5dafb68e5
commit
12483e70e4
|
@ -22,6 +22,9 @@ test.*
|
|||
# Autosaves
|
||||
*.dia~
|
||||
|
||||
## Logging files
|
||||
*.log
|
||||
|
||||
|
||||
## Deployment files
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from config import FlaskApplicationSettings, V5Config
|
|||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(FlaskApplicationSettings)
|
||||
app.v5logger = V5Config.v5logger()
|
||||
|
||||
# Check security of secret
|
||||
if FlaskApplicationSettings.SECRET_KEY == "a-random-secret-key":
|
||||
|
|
|
@ -397,7 +397,7 @@ class Member(User):
|
|||
Notify a user with a message.
|
||||
An hyperlink can be added to redirect to the notification source
|
||||
"""
|
||||
return
|
||||
# return
|
||||
n = Notification(self.id, message, href=href)
|
||||
db.session.add(n)
|
||||
db.session.commit()
|
||||
|
|
|
@ -45,6 +45,7 @@ def edit_account():
|
|||
db.session.commit()
|
||||
current_user.update_trophies("on-profile-update")
|
||||
flash('Modifications effectuées', 'ok')
|
||||
app.v5logger.info(f"<{current_user.name}> has edited their account")
|
||||
return redirect(request.url)
|
||||
else:
|
||||
flash('Erreur lors de la modification', 'error')
|
||||
|
@ -62,6 +63,7 @@ def ask_reset_password():
|
|||
m = Member.query.filter_by(email=form.email.data).first()
|
||||
if m is not None:
|
||||
send_reset_password_mail(m.name, m.email)
|
||||
app.v5logger.info(f"<{m.name}> has asked a password reset token")
|
||||
flash('Un email a été envoyé à l\'adresse renseignée', 'ok')
|
||||
return redirect(url_for('login'))
|
||||
elif request.method == "POST":
|
||||
|
@ -87,6 +89,7 @@ def reset_password(token):
|
|||
db.session.merge(m)
|
||||
db.session.commit()
|
||||
flash('Modifications effectuées', 'ok')
|
||||
app.v5logger.info(f"<{m.name}> has reset their password")
|
||||
return redirect(url_for('login'))
|
||||
else:
|
||||
flash('Erreur lors de la modification', 'error')
|
||||
|
@ -102,6 +105,7 @@ def delete_account():
|
|||
|
||||
if del_form.submit.data:
|
||||
if del_form.validate_on_submit():
|
||||
name = current_user.name
|
||||
if del_form.transfer.data:
|
||||
guest = Guest(current_user.generate_guest_name())
|
||||
db.session.add(guest)
|
||||
|
@ -116,6 +120,7 @@ def delete_account():
|
|||
logout_user()
|
||||
db.session.commit()
|
||||
flash('Compte supprimé', 'ok')
|
||||
app.v5logger.info(f"<{name}> has deleted their account ({'with' if del_form.transfer.data else 'without'} guest transfer)")
|
||||
return redirect(url_for('index'))
|
||||
else:
|
||||
flash('Erreur lors de la suppression du compte', 'error')
|
||||
|
@ -141,6 +146,7 @@ def register():
|
|||
|
||||
# Email validation message
|
||||
send_validation_mail(member.name, member.email)
|
||||
app.v5logger.info(f"<{member.name}> registered")
|
||||
|
||||
return redirect(url_for('validation') + "?email=" + form.email.data)
|
||||
return render('account/register.html', title='Register',
|
||||
|
@ -178,4 +184,5 @@ def activate_account(token):
|
|||
db.session.commit()
|
||||
|
||||
flash("L'email a bien été confirmé", "ok")
|
||||
app.v5logger.info(f"<{m.name}> has activated their account")
|
||||
return redirect(url_for('login'))
|
||||
|
|
|
@ -49,6 +49,7 @@ def login():
|
|||
login_user(member, remember=form.remember_me.data,
|
||||
duration=datetime.timedelta(days=7))
|
||||
member.update_trophies("on-login")
|
||||
app.v5logger.info(f"<{member.name}> has logged in")
|
||||
|
||||
# Redirect safely (https://huit.re/open-redirect)
|
||||
def is_safe_url(target):
|
||||
|
@ -71,8 +72,10 @@ def login():
|
|||
@login_required
|
||||
@check_csrf
|
||||
def logout():
|
||||
name = current_user.name
|
||||
logout_user()
|
||||
flash('Déconnexion réussie', 'info')
|
||||
app.v5logger.info(f"<{name}> has logged out")
|
||||
if request.referrer:
|
||||
return redirect(request.referrer)
|
||||
return redirect(url_for('index'))
|
||||
|
|
|
@ -28,5 +28,6 @@ def account_polls():
|
|||
db.session.commit()
|
||||
|
||||
flash(f"Le sondage {p.id} a été créé", "info")
|
||||
app.v5logger.info(f"<{current_user.name}> has created the form #{p.id}")
|
||||
|
||||
return render("account/polls.html", polls=polls, form=form)
|
||||
|
|
|
@ -68,6 +68,7 @@ def adm_edit_account(user_id):
|
|||
# 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')
|
||||
app.v5logger.info(f"[admin] <{current_user.name}> has edited <{user.name}>'s data")
|
||||
return redirect(request.url)
|
||||
else:
|
||||
flash('Erreur lors de la modification', 'error')
|
||||
|
@ -85,6 +86,7 @@ def adm_edit_account(user_id):
|
|||
db.session.merge(user)
|
||||
db.session.commit()
|
||||
flash('Modifications effectuées', 'ok')
|
||||
app.v5logger.info(f"[admin] <{current_user.name}> has edited <{user.name}>'s trophies")
|
||||
return redirect(request.url)
|
||||
else:
|
||||
flash("Erreur lors de la modification des trophées", 'error')
|
||||
|
@ -102,6 +104,7 @@ def adm_edit_account(user_id):
|
|||
db.session.merge(user)
|
||||
db.session.commit()
|
||||
flash('Modifications effectuées', 'ok')
|
||||
app.v5logger.info(f"[admin] <{current_user.name}> has edited <{user.name}>'s groups")
|
||||
return redirect(request.url)
|
||||
else:
|
||||
flash("Erreur lors de la modification des groupes", 'error')
|
||||
|
@ -151,6 +154,7 @@ def adm_delete_account(user_id):
|
|||
user.delete()
|
||||
db.session.commit()
|
||||
flash('Compte supprimé', 'ok')
|
||||
app.v5logger.info(f"[admin] <{current_user.name}> has deleted <{user.name}> account")
|
||||
return redirect(url_for('adm'))
|
||||
else:
|
||||
flash('Erreur lors de la suppression du compte', 'error')
|
||||
|
|
|
@ -42,6 +42,7 @@ def adm_login_as():
|
|||
# Create a safe token to flee when needed
|
||||
s = Serializer(app.config["SECRET_KEY"])
|
||||
vandal_token = s.dumps(current_user.id)
|
||||
vandal_name = current_user.name
|
||||
|
||||
# Login and display some messages
|
||||
login_user(user)
|
||||
|
@ -51,9 +52,11 @@ def adm_login_as():
|
|||
else:
|
||||
flash(f"Connecté en tant que {user.name}")
|
||||
|
||||
app.v5logger.info(f"[admin] <{vandal_name}> has logged in as <{user.name}>")
|
||||
|
||||
# Return the response
|
||||
resp = make_response(redirect(url_for('index')))
|
||||
resp.set_cookie('vandale', vandal_token)
|
||||
resp.set_cookie('vandale', vandal_token, path='/')
|
||||
return resp
|
||||
|
||||
# Else return form
|
||||
|
@ -75,14 +78,17 @@ def adm_logout_as():
|
|||
flash("Vous avez vraiment agi de manière stupide.", "error")
|
||||
abort(403)
|
||||
|
||||
victim_name = current_user.name
|
||||
user = Member.query.get(id)
|
||||
logout_user()
|
||||
login_user(user)
|
||||
|
||||
app.v5logger.info(f"[admin] <{user.name}> has logged out from <{victim_name}>'s account")
|
||||
|
||||
if request.referrer:
|
||||
resp = make_response(redirect(request.referrer))
|
||||
else:
|
||||
resp = make_response(redirect(url_for('index')))
|
||||
|
||||
resp.set_cookie('vandale', '', expires=0)
|
||||
resp.set_cookie('vandale', '', expires=0, path='/')
|
||||
return resp
|
||||
|
|
|
@ -73,6 +73,7 @@ def forum_page(f, page=1):
|
|||
current_user.update_trophies('new-post')
|
||||
|
||||
flash('Le sujet a bien été créé', 'ok')
|
||||
app.v5logger.info(f"<{t.author.name}> has created the topic #{t.id}")
|
||||
return redirect(url_for('forum_topic', f=f, page=(t,1)))
|
||||
|
||||
# Paginate topic pages
|
||||
|
|
|
@ -54,6 +54,7 @@ def forum_topic(f, page):
|
|||
current_user.update_trophies('new-post')
|
||||
|
||||
flash('Message envoyé', 'ok')
|
||||
app.v5logger.info(f"<{c.author.name}> has posted a the comment #{c.id}")
|
||||
# Redirect to empty the form
|
||||
return redirect(url_for('forum_topic', f=f, page=(t, "fin"),
|
||||
_anchor=str(c.id)))
|
||||
|
|
|
@ -34,7 +34,8 @@ def poll_vote(poll_id):
|
|||
db.session.add(answer)
|
||||
db.session.commit()
|
||||
|
||||
flash('Le vote a été pris en compte', 'info')
|
||||
flash('Le vote a été pris en compte', 'ok')
|
||||
app.v5logger.info(f"<{current_user.name}> has voted on the poll #{poll.id}")
|
||||
|
||||
if request.referrer:
|
||||
return redirect(request.referrer)
|
||||
|
|
|
@ -84,6 +84,10 @@ def edit_post(postid):
|
|||
for a, file in attachments:
|
||||
a.set_file(file)
|
||||
|
||||
flash('Modifications enregistrées', 'ok')
|
||||
admin_msg = "[admin] " if current_user != p.author else ""
|
||||
app.v5logger.info(f"{admin_msg}<{current_user.name}> has edited the post #{p.id}")
|
||||
|
||||
# Determine topic URL now, in case forum was changed
|
||||
if isinstance(p, Topic):
|
||||
return redirect(url_for('forum_topic', f=p.forum, page=(p,1)))
|
||||
|
@ -111,6 +115,10 @@ def delete_post(postid):
|
|||
if not current_user.can_delete_post(p):
|
||||
abort(403)
|
||||
|
||||
# Is a penalty deletion
|
||||
is_penalty = request.args.get('penalty') == 'True' \
|
||||
and current_user.priv('delete.posts')
|
||||
|
||||
# Users who need to have their trophies updated
|
||||
authors = set()
|
||||
|
||||
|
@ -126,16 +134,21 @@ def delete_post(postid):
|
|||
authors.add(comment.author)
|
||||
|
||||
if isinstance(p.author, Member):
|
||||
factor = 3 if request.args.get('penalty') == 'True' else 1
|
||||
factor = 3 if is_penalty else 1
|
||||
p.author.add_xp(xp * factor)
|
||||
db.session.merge(p.author)
|
||||
authors.add(p.author)
|
||||
|
||||
admin_msg = "[admin] " if current_user != p.author else ""
|
||||
p.delete()
|
||||
db.session.commit()
|
||||
|
||||
for author in authors:
|
||||
author.update_trophies("new-post")
|
||||
|
||||
flash("Le contenu a été supprimé", 'ok')
|
||||
penalty_msg = " (with penalty)" if is_penalty else ""
|
||||
app.v5logger.info(f"{admin_msg}<{current_user.name}> has deleted the post #{p.id}{penalty_msg}")
|
||||
|
||||
return redirect(next_page)
|
||||
|
||||
|
@ -149,6 +162,9 @@ def set_post_topcomment(postid):
|
|||
comment.thread.top_comment = comment
|
||||
db.session.add(comment.thread)
|
||||
db.session.commit()
|
||||
flash("Le post a été défini comme nouvel en-tête", 'ok')
|
||||
admin_msg = "[admin] " if current_user != comment.author else ""
|
||||
app.v5logger.info(f"{admin_msg}<{current_user.name}> has set a new top comment on thread #{comment.thread.id}")
|
||||
|
||||
return redirect(request.referrer)
|
||||
|
||||
|
@ -191,8 +207,11 @@ def move_post(postid):
|
|||
comment.thread = thread
|
||||
db.session.add(comment)
|
||||
db.session.commit()
|
||||
flash("Le topic a été déplacé", 'ok')
|
||||
admin_msg = "[admin] " if current_user != comment.author else ""
|
||||
app.v5logger.info(f"{admin_msg}<{current_user.name}> has moved the comment #{comment.id} to thread #{thread.id}")
|
||||
return redirect(url_for('forum_topic', f=t.forum, page=(t,1)))
|
||||
|
||||
|
||||
return render('post/move_post.html', comment=comment,
|
||||
search_form=search_form, move_form=move_form)
|
||||
|
||||
|
@ -212,8 +231,10 @@ def lock_thread(postid):
|
|||
db.session.commit()
|
||||
|
||||
if post.thread.locked:
|
||||
flash(f"Le thread a été verrouillé")
|
||||
flash(f"Le thread a été verrouillé", 'ok')
|
||||
app.v5logger.info(f"[admin] <{current_user.name}> has locked the thread #{post.thread.id}")
|
||||
else:
|
||||
flash(f"Le thread a été déverrouillé")
|
||||
flash(f"Le thread a été déverrouillé", 'ok')
|
||||
app.v5logger.info(f"[admin] <{current_user.name}> has unlocked the thread #{post.thread.id}")
|
||||
|
||||
return redirect(request.referrer)
|
|
@ -41,6 +41,7 @@ def program_view(page):
|
|||
current_user.update_trophies('new-post')
|
||||
|
||||
flash('Message envoyé', 'ok')
|
||||
app.v5logger.info(f"<{c.author.name}> has posted a the comment #{c.id}")
|
||||
# Redirect to empty the form
|
||||
return redirect(url_for('program_view', page=(p, "fin"), _anchor=str(c.id)))
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ def program_submit():
|
|||
current_user.update_trophies('new-program')
|
||||
|
||||
flash('Le programme a bien été soumis', 'ok')
|
||||
app.v5logger.info(f"<{p.author.name}> has submitted the program #{c.id}")
|
||||
return redirect(url_for('program_index'))
|
||||
|
||||
return render('/programs/submit.html', form=form)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% import "widgets/editor.html" as widget_editor %}
|
||||
{% import "widgets/tag_selector.html" as widget_tag_selector with context %}
|
||||
|
||||
{% set tabtitle = f"Programmes - Soumettre un programme" %}
|
||||
{% set tabtitle = "Programmes - Soumettre un programme" %}
|
||||
|
||||
{% block title %}
|
||||
<a href="{{ url_for('program_index') }}">Programmes</a> » <h1>Soumettre un programme</h1>
|
||||
|
|
13
config.py
13
config.py
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
try:
|
||||
|
@ -86,6 +87,18 @@ class DefaultConfig(object):
|
|||
# Tab title prefix. Useful to dissociate local/dev/prod tabs
|
||||
TABTITLE_PREFIX = ""
|
||||
|
||||
@staticmethod
|
||||
def v5logger():
|
||||
""" A fully configured logger for v5 activity logs """
|
||||
logger = logging.getLogger('v5')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s')
|
||||
handler = logging.FileHandler('v5_activity.log')
|
||||
handler.setLevel(logging.DEBUG)
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
return logger
|
||||
|
||||
|
||||
class V5Config(LocalConfig, DefaultConfig):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue