2019-08-20 17:34:00 +02:00
|
|
|
from app import db
|
|
|
|
|
|
|
|
|
|
|
|
class Forum(db.Model):
|
|
|
|
__tablename__ = 'forum'
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
|
2019-09-02 21:35:16 +02:00
|
|
|
# Forum name, as displayed on the site (eg. "Problèmes de transfert")
|
2019-08-20 17:34:00 +02:00
|
|
|
name = db.Column(db.Unicode(64))
|
2019-09-02 21:35:16 +02:00
|
|
|
# Privilege prefix (sort of slug) for single-forum privileges (lowercase)
|
|
|
|
prefix = db.Column(db.Unicode(64))
|
|
|
|
# Forum description, as displayed on the site
|
|
|
|
descr = db.Column(db.UnicodeText)
|
|
|
|
# Forum URL, for dynamic routes
|
|
|
|
url = db.Column(db.String(64))
|
2019-08-20 17:34:00 +02:00
|
|
|
|
|
|
|
# Relationships
|
|
|
|
parent_id = db.Column(db.Integer, db.ForeignKey('forum.id'), nullable=True)
|
2020-08-05 22:52:56 +02:00
|
|
|
parent = db.relationship('Forum', backref='sub_forums', remote_side=id,
|
|
|
|
lazy=True, foreign_keys=parent_id)
|
2019-08-24 19:17:13 +02:00
|
|
|
|
2019-11-21 15:31:46 +01:00
|
|
|
# Other fields populated automatically through relations:
|
2021-02-20 19:30:18 +01:00
|
|
|
# <sub_forums> Children forums
|
|
|
|
# <topics> List of topics in this exact forum (of type Topic)
|
2019-08-20 17:34:00 +02:00
|
|
|
|
2020-08-02 17:28:43 +02:00
|
|
|
# Some configuration
|
|
|
|
TOPICS_PER_PAGE = 30
|
|
|
|
|
2019-09-02 21:35:16 +02:00
|
|
|
def __init__(self, url, name, prefix, descr="", parent=None):
|
|
|
|
self.url = url
|
2019-08-20 17:34:00 +02:00
|
|
|
self.name = name
|
2019-09-02 21:35:16 +02:00
|
|
|
self.descr = descr
|
|
|
|
self.prefix = prefix
|
|
|
|
|
|
|
|
if isinstance(parent, str):
|
|
|
|
self.parent = Forum.query.filter_by(url=str).first()
|
|
|
|
else:
|
|
|
|
self.parent = parent
|
2019-08-20 17:34:00 +02:00
|
|
|
|
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
|
|
|
def is_news(self):
|
|
|
|
"""Whether this forum is a news board."""
|
|
|
|
return (self.parent is not None) and (self.parent.prefix == "news")
|
|
|
|
|
|
|
|
def is_default_accessible(self):
|
|
|
|
"""Whether this forum can be read without privileges."""
|
|
|
|
return (self.prefix != "admin") and (self.prefix != "creativecalc")
|
|
|
|
|
|
|
|
def is_default_postable(self):
|
|
|
|
"""Whether this forum can be posted to without privileges."""
|
|
|
|
return self.is_default_accessible() and (not self.is_news()) and \
|
|
|
|
(self.sub_forums == [])
|
|
|
|
|
2019-09-05 21:37:55 +02:00
|
|
|
def post_count(self):
|
|
|
|
"""Number of posts in every topic of the forum, without subforums."""
|
2020-09-24 00:22:20 +02:00
|
|
|
# TODO: optimize this with real ORM
|
|
|
|
return sum(t.thread.comments.count() for t in self.topics)
|
2019-11-21 15:31:46 +01:00
|
|
|
|
2020-11-01 10:49:24 +01:00
|
|
|
def delete(self):
|
|
|
|
"""Recursively delete forum and all associated contents."""
|
|
|
|
for t in self.topics:
|
|
|
|
t.delete()
|
|
|
|
db.session.commit()
|
|
|
|
db.session.delete(self)
|
|
|
|
|
2019-11-21 15:31:46 +01:00
|
|
|
def __repr__(self):
|
|
|
|
return f'<Forum: {self.name}>'
|