Browse Source

Made a many-to-many relation for the moderators.
Rewrapped some lines.

sh4nks 11 years ago
parent
commit
318e06afb4

+ 90 - 54
flaskbb/admin/forms.py

@@ -75,14 +75,18 @@ class UserForm(Form):
     notes = TextAreaField("Notes", validators=[
         Optional(), Length(min=0, max=5000)])
 
-    primary_group = QuerySelectField("Primary Group",
-                                     query_factory=select_primary_group,
-                                     get_label="name")
-
-    secondary_groups = QuerySelectMultipleField("Secondary Groups",
-                                                query_factory=select_primary_group,  # TODO: Template rendering errors "NoneType is not callable" without this, figure out why.
-                                                allow_blank=True,
-                                                get_label="name")
+    primary_group = QuerySelectField(
+        "Primary Group",
+        query_factory=select_primary_group,
+        get_label="name")
+
+    secondary_groups = QuerySelectMultipleField(
+        "Secondary Groups",
+        # TODO: Template rendering errors "NoneType is not callable"
+        #       without this, figure out why.
+        query_factory=select_primary_group,
+        allow_blank=True,
+        get_label="name")
 
     def validate_username(self, field):
         if hasattr(self, "user"):
@@ -133,35 +137,48 @@ class GroupForm(Form):
     description = TextAreaField("Description", validators=[
         Optional()])
 
-    admin = BooleanField("Is Admin Group?",
-                         description="With this option the group has access \
-                                      to the admin panel.")
-    super_mod = BooleanField("Is Super Moderator Group?",
-                             description="Check this if the users in this \
-                                          group are allowed to moderate every \
-                                          forum")
-    mod = BooleanField("Is Moderator Group?",
-                       description="Check this if the users in this group are \
-                                    allowed to moderate specified forums")
-    banned = BooleanField("Is Banned Group?",
-                          description="Only one Banned group is allowed")
-    guest = BooleanField("Is Guest Group?",
-                         description="Only one Guest group is allowed")
-    editpost = BooleanField("Can edit posts",
-                            description="Check this if the users in this \
-                                         group can edit posts")
-    deletepost = BooleanField("Can delete posts",
-                              description="Check this is the users in this \
-                                           group can delete posts")
-    deletetopic = BooleanField("Can delete topics",
-                               description="Check this is the users in this \
-                                            group can delete topics")
-    posttopic = BooleanField("Can create topics",
-                             description="Check this is the users in this \
-                                          group can create topics")
-    postreply = BooleanField("Can post replies",
-                             description="Check this is the users in this \
-                                          group can post replies")
+    admin = BooleanField(
+        "Is Admin Group?",
+        description="With this option the group has access to the admin panel."
+    )
+    super_mod = BooleanField(
+        "Is Super Moderator Group?",
+        description="Check this if the users in this group are allowed to \
+                     moderate every forum"
+    )
+    mod = BooleanField(
+        "Is Moderator Group?",
+        description="Check this if the users in this group are allowed to \
+                     moderate specified forums"
+    )
+    banned = BooleanField(
+        "Is Banned Group?",
+        description="Only one Banned group is allowed"
+    )
+    guest = BooleanField(
+        "Is Guest Group?",
+        description="Only one Guest group is allowed"
+    )
+    editpost = BooleanField(
+        "Can edit posts",
+        description="Check this if the users in this group can edit posts"
+    )
+    deletepost = BooleanField(
+        "Can delete posts",
+        description="Check this is the users in this group can delete posts"
+    )
+    deletetopic = BooleanField(
+        "Can delete topics",
+        description="Check this is the users in this group can delete topics"
+    )
+    posttopic = BooleanField(
+        "Can create topics",
+        description="Check this is the users in this group can create topics"
+    )
+    postreply = BooleanField(
+        "Can post replies",
+        description="Check this is the users in this group can post replies"
+    )
 
     def validate_name(self, field):
         if hasattr(self, "group"):
@@ -219,8 +236,6 @@ class AddGroupForm(GroupForm):
 
 
 class ForumForm(Form):
-    _moderators = set()
-
     title = TextField("Forum Title", validators=[
         Required(message="Forum title required")])
 
@@ -239,37 +254,58 @@ class ForumForm(Form):
         description="The category that contains this forum."
     )
 
-    moderators = TextField("Moderators",
-                           description="Comma seperated usernames. Leave it \
-                                        blank if you do not want to set any \
-                                        moderators.")
+    moderators = TextField(
+        "Moderators",
+        description="Comma seperated usernames. Leave it blank if you do not \
+                     want to set any moderators."
+    )
 
-    locked = BooleanField("Locked?", description="Disable new posts and topics \
-                                                  in this forum.")
+    show_moderators = BooleanField(
+        "Show Moderators",
+        description="Do you want show the moderators on the index page?"
+    )
+
+    locked = BooleanField(
+        "Locked?",
+        description="Disable new posts and topics in this forum."
+    )
+
+    def validate_show_moderators(self, field):
+        if field.data and not self.moderators.data:
+            raise ValidationError("You also need to specify some moderators.")
 
     def validate_moderators(self, field):
+        approved_moderators = list()
+
         if field.data:
-            # Check if the usernames exist
-            for moderator in field.data.split(","):
+            # convert the CSV string in a list
+            moderators = field.data.split(",")
+            # remove leading and ending spaces
+            moderators = [mod.strip() for mod in moderators]
+            for moderator in moderators:
+                # Check if the usernames exist
                 user = User.query.filter_by(username=moderator).first()
 
                 # Check if the user has the permissions to moderate a forum
                 if user:
-                    if not user.get_permissions()["mod"]:
-                        raise ValidationError("The user is not in a moderators \
-                            group")
+                    if not (user.get_permissions()["mod"] or
+                            user.get_permissions()["admin"] or
+                            user.get_permissions()["super_mod"]):
+                        raise ValidationError("%s is not in a moderators \
+                            group" % user.username)
                     else:
-                        self._moderators.add(user.id)
+                        approved_moderators.append(user)
                 else:
-                    raise ValidationError("User not found")
-            field.data = self._moderators
+                    raise ValidationError("User %s not found" % moderator)
+            field.data = approved_moderators
 
     def save(self):
         forum = Forum(title=self.title.data,
                       description=self.description.data,
                       position=self.position.data)
 
-        if self.moderators.data and not self.is_category.data:
+        if self.moderators.data:
+            # is already validated
             forum.moderators = self.moderators.data
 
         forum.category_id = self.category.data.id

+ 5 - 7
flaskbb/admin/views.py

@@ -199,7 +199,6 @@ def edit_forum(forum_id):
     forum = Forum.query.filter_by(id=forum_id).first_or_404()
 
     form = ForumForm()
-    form._id = forum.id  # Used for validation only.
 
     if form.validate_on_submit():
         forum.title = form.title.data
@@ -207,11 +206,9 @@ def edit_forum(forum_id):
         forum.position = form.position.data
         forum.locked = form.locked.data
         forum.category_id = form.category.data.id
+        forum.show_moderators = form.show_moderators.data
 
-        if form.moderators.data:
-            forum.moderators = form.moderators.data
-
-        forum.save()
+        forum.save(moderators=form.moderators.data)
 
         flash("Forum successfully edited.", "success")
         return redirect(url_for("admin.edit_forum", forum_id=forum.id))
@@ -221,10 +218,11 @@ def edit_forum(forum_id):
         form.position.data = forum.position
         form.category.data = forum.category
         form.locked.data = forum.locked
+        form.show_moderators.data = forum.show_moderators
 
         if forum.moderators:
-            mods = User.query.filter(User.id.in_(forum.moderators)).all()
-            form.moderators.data = ",".join([mod.username for mod in mods])
+            form.moderators.data = ",".join([user.username
+                                            for user in forum.moderators])
         else:
             form.moderators.data = None
 

+ 90 - 61
flaskbb/forum/models.py

@@ -13,10 +13,72 @@ from datetime import datetime, timedelta
 from flask import current_app
 
 from flaskbb.extensions import db
-from flaskbb.utils.types import SetType, MutableSet
 from flaskbb.utils.query import TopicQuery
 
 
+moderators = db.Table(
+    'moderators',
+    db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
+    db.Column('forum_id', db.Integer(),
+              db.ForeignKey('forums.id', use_alter=True, name="fk_forum_id")))
+
+
+topictracker = db.Table(
+    'topictracker',
+    db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
+    db.Column('topic_id', db.Integer(),
+              db.ForeignKey('topics.id', use_alter=True, name="fk_topic_id")))
+
+
+class TopicsRead(db.Model):
+    __tablename__ = "topicsread"
+
+    user_id = db.Column(db.Integer, db.ForeignKey("users.id"),
+                        primary_key=True)
+    topic_id = db.Column(db.Integer,
+                         db.ForeignKey("topics.id", use_alter=True,
+                                       name="fk_topic_id"),
+                         primary_key=True)
+    forum_id = db.Column(db.Integer,
+                         db.ForeignKey("forums.id", use_alter=True,
+                                       name="fk_tr_forum_id"),
+                         primary_key=True)
+    last_read = db.Column(db.DateTime, default=datetime.utcnow())
+
+    def save(self):
+        db.session.add(self)
+        db.session.commit()
+        return self
+
+    def delete(self):
+        db.session.delete(self)
+        db.session.commit()
+        return self
+
+
+class ForumsRead(db.Model):
+    __tablename__ = "forumsread"
+
+    user_id = db.Column(db.Integer, db.ForeignKey("users.id"),
+                        primary_key=True)
+    forum_id = db.Column(db.Integer,
+                         db.ForeignKey("topics.id", use_alter=True,
+                                       name="fk_forum_id"),
+                         primary_key=True)
+    last_read = db.Column(db.DateTime, default=datetime.utcnow())
+    cleared = db.Column(db.DateTime)
+
+    def save(self):
+        db.session.add(self)
+        db.session.commit()
+        return self
+
+    def delete(self):
+        db.session.delete(self)
+        db.session.commit()
+        return self
+
+
 class Post(db.Model):
     __tablename__ = "posts"
 
@@ -239,6 +301,8 @@ class Topic(db.Model):
                    Topic.forum_id == self.forum_id).\
             count()
 
+        TopicsRead.query.filter_by(topic_id=self.id).delete()
+
         db.session.commit()
         return self
 
@@ -338,15 +402,13 @@ class Forum(db.Model):
     category_id = db.Column(db.Integer, db.ForeignKey("categories.id"))
     title = db.Column(db.String)
     description = db.Column(db.String)
-    position = db.Column(db.Integer, default=0)
+    position = db.Column(db.Integer, default=1)
     locked = db.Column(db.Boolean, default=False)
+    show_moderators = db.Column(db.Boolean, default=False)
 
     post_count = db.Column(db.Integer, default=0)
     topic_count = db.Column(db.Integer, default=0)
 
-    # TODO: Make a own relation for this
-    moderators = db.Column(MutableSet.as_mutable(SetType))
-
     # One-to-one
     last_post_id = db.Column(db.Integer, db.ForeignKey("posts.id"))
     last_post = db.relationship("Post", backref="last_post_forum",
@@ -356,6 +418,12 @@ class Forum(db.Model):
     topics = db.relationship("Topic", backref="forum", lazy="joined",
                              cascade="all, delete-orphan")
 
+    moderators = \
+        db.relationship("User", secondary=moderators,
+                        primaryjoin=(moderators.c.forum_id == id),
+                        backref=db.backref("forummoderator", lazy="dynamic"),
+                        lazy="joined")
+
     # Methods
     def __repr__(self):
         """Set to a unique key specific to the object in the database.
@@ -363,14 +431,17 @@ class Forum(db.Model):
         """
         return "<{} {}>".format(self.__class__.__name__, self.id)
 
-    def add_moderator(self, user_id):
-        self.moderators.add(user_id)
+    def save(self, moderators=None):
+        """Saves a forum"""
+        if moderators is not None:
+            for moderator in self.moderators:
+                self.moderators.remove(moderator)
+            db.session.commit()
 
-    def remove_moderator(self, user_id):
-        self.moderators.remove(user_id)
+            for moderator in moderators:
+                if moderator:
+                    self.moderators.append(moderator)
 
-    def save(self):
-        """Saves a forum"""
         db.session.add(self)
         db.session.commit()
         return self
@@ -385,11 +456,18 @@ class Forum(db.Model):
         db.session.delete(self)
         db.session.commit()
 
+        # Delete all entries from the ForumsRead and TopicsRead relation
+        ForumsRead.query.filter_by(forum_id=self.id).delete()
+        TopicsRead.query.filter_by(forum_id=self.id).delete()
+
         # Update the users post count
         if users:
+            users_list = []
             for user in users:
                 user.post_count = Post.query.filter_by(user_id=user.id).count()
-                db.session.commit()
+                users_list.append(user)
+            db.session.add_all(users_list)
+            db.session.commit()
 
         return self
 
@@ -432,52 +510,3 @@ class Category(db.Model):
         db.session.delete(self)
         db.session.commit()
         return self
-
-
-topictracker = db.Table(
-    'topictracker',
-    db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
-    db.Column('topic_id', db.Integer(), db.ForeignKey('topics.id')))
-
-
-class TopicsRead(db.Model):
-    __tablename__ = "topicsread"
-
-    user_id = db.Column(db.Integer, db.ForeignKey("users.id"),
-                        primary_key=True)
-    topic_id = db.Column(db.Integer, db.ForeignKey("topics.id"),
-                         primary_key=True)
-    forum_id = db.Column(db.Integer, db.ForeignKey("forums.id"),
-                         primary_key=True)
-    last_read = db.Column(db.DateTime, default=datetime.utcnow())
-
-    def save(self):
-        db.session.add(self)
-        db.session.commit()
-        return self
-
-    def delete(self):
-        db.session.delete(self)
-        db.session.commit()
-        return self
-
-
-class ForumsRead(db.Model):
-    __tablename__ = "forumsread"
-
-    user_id = db.Column(db.Integer, db.ForeignKey("users.id"),
-                        primary_key=True)
-    forum_id = db.Column(db.Integer, db.ForeignKey("topics.id"),
-                         primary_key=True)
-    last_read = db.Column(db.DateTime, default=datetime.utcnow())
-    cleared = db.Column(db.DateTime)
-
-    def save(self):
-        db.session.add(self)
-        db.session.commit()
-        return self
-
-    def delete(self):
-        db.session.delete(self)
-        db.session.commit()
-        return self

+ 1 - 0
flaskbb/templates/admin/forum_form.html

@@ -15,6 +15,7 @@
         {{ horizontal_field(form.position) }}
 
         {{ horizontal_field(form.moderators) }}
+        {{ render_boolean_field(form.show_moderators) }}
 
         {{ render_boolean_field(form.locked) }}
 

+ 8 - 0
flaskbb/templates/forum/index.html

@@ -41,6 +41,14 @@
                     {% autoescape false %}
                     {{ forum[0].description|markup }}
                     {% endautoescape %}
+                    {% if forum[0].show_moderators %}
+                    <div class="forum-moderators">
+                        Moderators:
+                        {% for moderator in forum[0].moderators %}
+                        <a href="{{ url_for('user.profile', username=moderator.username) }}">{{ moderator.username }}</a>{% if not loop.last %}, {% endif %}
+                        {% endfor %}
+                    </div>
+                    {% endif %}
                 </div>
             </td>
 

+ 0 - 2
flaskbb/user/models.py

@@ -297,8 +297,6 @@ class User(db.Model, UserMixin):
 
     def delete(self):
         """Deletes the User."""
-        groups_users.delete().where(groups_users.c.user_id == self.id)
-        topictracker.delete().where(topictracker.c.user_id == self.id)
         PrivateMessage.query.filter_by(user_id=self.id).delete()
         ForumsRead.query.filter_by(user_id=self.id).delete()
         TopicsRead.query.filter_by(user_id=self.id).delete()