PCv5/app/routes/forum/index.py

103 lines
3.5 KiB
Python
Raw Normal View History

from flask_login import current_user
from flask import request, redirect, url_for, abort, flash
from app import app, db
from config import V5Config
from app.utils.render import render
2023-06-12 20:04:20 +02:00
from app.utils.glados import say, BOLD
from app.forms.forum import TopicCreationForm, AnonymousTopicCreationForm
from app.models.forum import Forum
from app.models.topic import Topic
from app.models.thread import Thread
from app.models.comment import Comment
2020-08-25 22:57:45 +02:00
from app.models.user import Guest
from app.models.attachment import Attachment
@app.route('/forum/')
def forum_index():
return render('/forum/index.html')
@app.route('/forum/<forum:f>/', methods=['GET', 'POST'])
@app.route('/forum/<forum:f>/p/<int:page>', methods=['GET', 'POST'])
def forum_page(f, page=1):
review of privileges and forum permissions * Sorted privileges into categories, similar to the v4.3 style Added privilege check utilities: * Forum: is_news(), is_default_accessible() and is_default_postable() * Member: can_access_forum(), can_post_in_forum(), can_edit_post(), and can_delete_post() Unfortunately current_user is not a Guest when logged out, so one cannot usually write current_user.can_*() without checking for authentication first, so the checks are still somewhat verbose. Reviewed forum permissions; the following permission issues have been fixed (I have tested most but not all of them prior to fixing): * app/routes/forum/index.py: Users that were not meant to access a forum could still obtain a listing of the topics * app/routes/forum/topic.py: Users that were not meant to see topics could still read them by browsing the URL * app/routes/forum/topic.py: Authenticated users could post in any topic, including ones that they should not have access to * app/routes/posts/edit.py: Users with edit.posts (eg. mods) could edit and delete messages in forums they can't access (eg. creativecalc) * app/templates/account/user.html: Users with admin panel access would see account editing links they can't use (affects developers) * app/templates/base/navbar/forum.html: The "Forum" tab would list all forums including ones the user doesn't have access to * app/templates/forum/index.html: Users would see every single forum, including ones they can't access * app/template/widgets/thread.html: Anyone would see Edit/Delete links on every message, even though most were unusable Miscellaneous changes: * app/routes/forum/topic.py: Ordered comments by date as intended, which I assume worked by chance until now * Removed the old assets/privs.txt files which is now superseded by the list implemented in app/data/groups.yaml This commit changes group and forum information, run master.py with: @> forums update @> groups update
2021-02-26 18:29:25 +01:00
if not f.is_default_accessible() and not (
current_user.is_authenticated and current_user.can_access_forum(f)):
abort(403)
if current_user.is_authenticated:
form = TopicCreationForm()
else:
form = AnonymousTopicCreationForm()
if form.validate_on_submit() and (
review of privileges and forum permissions * Sorted privileges into categories, similar to the v4.3 style Added privilege check utilities: * Forum: is_news(), is_default_accessible() and is_default_postable() * Member: can_access_forum(), can_post_in_forum(), can_edit_post(), and can_delete_post() Unfortunately current_user is not a Guest when logged out, so one cannot usually write current_user.can_*() without checking for authentication first, so the checks are still somewhat verbose. Reviewed forum permissions; the following permission issues have been fixed (I have tested most but not all of them prior to fixing): * app/routes/forum/index.py: Users that were not meant to access a forum could still obtain a listing of the topics * app/routes/forum/topic.py: Users that were not meant to see topics could still read them by browsing the URL * app/routes/forum/topic.py: Authenticated users could post in any topic, including ones that they should not have access to * app/routes/posts/edit.py: Users with edit.posts (eg. mods) could edit and delete messages in forums they can't access (eg. creativecalc) * app/templates/account/user.html: Users with admin panel access would see account editing links they can't use (affects developers) * app/templates/base/navbar/forum.html: The "Forum" tab would list all forums including ones the user doesn't have access to * app/templates/forum/index.html: Users would see every single forum, including ones they can't access * app/template/widgets/thread.html: Anyone would see Edit/Delete links on every message, even though most were unusable Miscellaneous changes: * app/routes/forum/topic.py: Ordered comments by date as intended, which I assume worked by chance until now * Removed the old assets/privs.txt files which is now superseded by the list implemented in app/data/groups.yaml This commit changes group and forum information, run master.py with: @> forums update @> groups update
2021-02-26 18:29:25 +01:00
(V5Config.ENABLE_GUEST_POST and f.is_default_postable()) or \
(current_user.is_authenticated and current_user.can_post_in_forum(f))):
# Manage author
if current_user.is_authenticated:
author = current_user
else:
author = Guest(form.pseudo.data)
db.session.add(author)
# First create the thread, then the comment, then the topic
th = Thread()
db.session.add(th)
db.session.commit()
c = Comment(author, form.message.data, th)
db.session.add(c)
db.session.commit()
th.set_top_comment(c)
db.session.merge(th)
t = Topic(f, author, form.title.data, th)
db.session.add(t)
db.session.commit()
# Manage files
attachments = []
for file in form.attachments.data:
if file.filename != "":
a = Attachment(file, c)
attachments.append((a, file))
db.session.add(a)
db.session.commit()
for a, file in attachments:
a.set_file(file)
2019-12-10 11:22:56 +01:00
# Update member's xp and trophies
if current_user.is_authenticated:
current_user.add_xp(2) # 2 points for a topic
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}")
2023-06-11 23:05:03 +02:00
if f.is_default_accessible():
say(f"Nouveau topic de {author.name} : {BOLD}{t.title}{BOLD}")
2023-06-12 20:04:20 +02:00
say(url_for('forum_topic', f=f, page=(t, 1), _external=True))
2023-06-11 23:05:03 +02:00
return redirect(url_for('forum_topic', f=f, page=(t,1)))
# Paginate topic pages
# TODO: order by last comment date
topics = f.topics.order_by(Topic.date_created.desc()).paginate(
page, Forum.TOPICS_PER_PAGE, True)
# Count comments; this direct request avoids performing one request for
# each topic.thread.comments.count() in the view, which the database
# doesn't really appreciate performance-wise.
selection = " OR ".join(f"thread_id={t.thread.id}" for t in topics.items)
selection = "WHERE " + selection if selection else ""
comment_counts = db.session.execute(f"""
SELECT thread_id, COUNT(*) FROM comment {selection}
GROUP BY thread_id
""")
comment_counts = dict(list(comment_counts))
return render('/forum/forum.html', f=f, topics=topics, form=form,
comment_counts=comment_counts)