Browse Source

Added functionality to report posts

sh4nks 11 years ago
parent
commit
9d314eea3b

+ 1 - 1
README.md

@@ -21,7 +21,7 @@ using the micro framework Flask.
 * ~~"Link to"-Forum type~~
 * ~~Move a topic in a other forum~~
 * Merging 2 topics together
-* Reporting posts
+* ~~Reporting posts~~
 * Userstyles (e.q.: colored username)
 * ~~Database migrations~~
 * A own theme ~~and make FlaskBB themable with Flask-Themes2~~

+ 63 - 10
flaskbb/admin/views.py

@@ -9,16 +9,18 @@
     :license: BSD, see LICENSE for more details.
 """
 import sys
+from datetime import datetime
 
 from flask import (Blueprint, current_app, request, redirect, url_for, flash,
                    __version__ as flask_version)
+from flask.ext.login import current_user
 
 from flaskbb import __version__ as flaskbb_version
 from flaskbb.utils.helpers import render_template
 from flaskbb.utils.decorators import admin_required
 from flaskbb.extensions import db
 from flaskbb.user.models import User, Group
-from flaskbb.forum.models import Post, Topic, Forum, Category
+from flaskbb.forum.models import Post, Topic, Forum, Category, Report
 from flaskbb.admin.forms import (AddUserForm, EditUserForm, AddGroupForm,
                                  EditGroupForm, EditForumForm, AddForumForm,
                                  CategoryForm)
@@ -72,6 +74,62 @@ def forums():
     return render_template("admin/forums.html", categories=categories)
 
 
+@admin.route("/reports")
+@admin_required
+def reports():
+    page = request.args.get("page", 1, type=int)
+    reports = Report.query.\
+        order_by(Report.id.asc()).\
+        paginate(page, current_app.config['USERS_PER_PAGE'], False)
+
+    return render_template("admin/reports.html", reports=reports)
+
+
+@admin.route("/reports/unread")
+@admin_required
+def unread_reports():
+    page = request.args.get("page", 1, type=int)
+    reports = Report.query.\
+        filter(Report.zapped == None).\
+        order_by(Report.id.desc()).\
+        paginate(page, current_app.config['USERS_PER_PAGE'], False)
+
+    return render_template("admin/unread_reports.html", reports=reports)
+
+
+@admin.route("/reports/<int:report_id>/markread")
+@admin.route("/reports/markread")
+@admin_required
+def report_markread(report_id=None):
+    # mark single report as read
+    if report_id:
+
+        report = Report.query.filter_by(id=report_id).first_or_404()
+        if report.zapped:
+            flash("Report %s is already marked as read" % report.id, "success")
+            return redirect(url_for("admin.reports"))
+
+        report.zapped_by = current_user.id
+        report.zapped = datetime.utcnow()
+        report.save()
+        flash("Report %s marked as read" % report.id, "success")
+        return redirect(url_for("admin.reports"))
+
+    # mark all as read
+    reports = Report.query.filter(Report.zapped == None).all()
+    report_list = []
+    for report in reports:
+        report.zapped_by = current_user.id
+        report.zapped = datetime.utcnow()
+        report_list.append(report)
+
+    db.session.add_all(report_list)
+    db.session.commit()
+
+    flash("All reports were marked as read", "success")
+    return redirect(url_for("admin.reports"))
+
+
 @admin.route("/users/<int:user_id>/edit", methods=["GET", "POST"])
 @admin_required
 def edit_user(user_id):
@@ -85,15 +143,7 @@ def edit_user(user_id):
     form = EditUserForm(user)
     form.secondary_groups.query = secondary_group_query
     if form.validate_on_submit():
-        user.username = form.username.data
-        user.email = form.email.data
-        user.birthday = form.birthday.data
-        user.gender = form.gender.data
-        user.website = form.website.data
-        user.location = form.location.data
-        user.signature = form.signature.data
-        user.avatar = form.avatar.data
-        user.notes = form.notes.data
+        form.populate_obj(user)
         user.primary_group_id = form.primary_group.data.id
 
        # Don't override the password
@@ -260,6 +310,7 @@ def add_forum(category_id=None):
 
 
 @admin.route("/category/add", methods=["GET", "POST"])
+@admin_required
 def add_category():
     form = CategoryForm()
 
@@ -273,6 +324,7 @@ def add_category():
 
 
 @admin.route("/category/<int:category_id>/edit", methods=["GET", "POST"])
+@admin_required
 def edit_category(category_id):
     category = Category.query.filter_by(id=category_id).first_or_404()
 
@@ -291,6 +343,7 @@ def edit_category(category_id):
 
 
 @admin.route("/category/<int:category_id>/delete", methods=["GET", "POST"])
+@admin_required
 def delete_category(category_id):
     category = Category.query.filter_by(id=category_id).first_or_404()
 

+ 12 - 1
flaskbb/forum/forms.py

@@ -12,7 +12,7 @@ from flask.ext.wtf import Form
 from wtforms import TextAreaField, TextField
 from wtforms.validators import Required
 
-from flaskbb.forum.models import Topic, Post
+from flaskbb.forum.models import Topic, Post, Report
 
 
 class QuickreplyForm(Form):
@@ -43,3 +43,14 @@ class NewTopicForm(ReplyForm):
         topic = Topic(title=self.title.data)
         post = Post(content=self.content.data)
         return topic.save(user=user, forum=forum, post=post)
+
+
+class ReportForm(Form):
+    reason = TextAreaField("Reason", validators=[
+        Required(message="Please insert a reason why you want to report this \
+                          post")
+    ])
+
+    def save(self, user, post):
+        report = Report(**self.data)
+        return report.save(user, post)

+ 47 - 0
flaskbb/forum/models.py

@@ -83,6 +83,53 @@ class ForumsRead(db.Model):
         return self
 
 
+class Report(db.Model):
+    __tablename__ = "reports"
+
+    id = db.Column(db.Integer, primary_key=True)
+    reporter_id = db.Column(db.Integer, db.ForeignKey("users.id"),
+                            nullable=False)
+    reported = db.Column(db.DateTime, default=datetime.utcnow())
+    post_id = db.Column(db.Integer, db.ForeignKey("posts.id"), nullable=False)
+    zapped = db.Column(db.DateTime)
+    zapped_by = db.Column(db.Integer, db.ForeignKey("users.id"))
+    reason = db.Column(db.String)
+
+    post = db.relationship("Post", backref="report", lazy="joined")
+    reporter = db.relationship("User", lazy="joined",
+                               foreign_keys=[reporter_id])
+    zapper = db.relationship("User", lazy="joined", foreign_keys=[zapped_by])
+
+    def save(self, post=None, user=None):
+        """Saves a report.
+
+        :param post: The post that should be reported
+
+        :param user: The user who has reported the post
+
+        :param reason: The reason why the user has reported the post
+        """
+
+        if self.id:
+            db.session.add(self)
+            db.session.commit()
+            return self
+
+        if post and user:
+            self.reporter_id = user.id
+            self.reported = datetime.utcnow()
+            self.post_id = post.id
+
+        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"
 

+ 15 - 1
flaskbb/forum/views.py

@@ -24,7 +24,8 @@ from flaskbb.utils.permissions import (can_post_reply, can_post_topic,
                                        can_move_topic)
 from flaskbb.forum.models import (Category, Forum, Topic, Post, ForumsRead,
                                   TopicsRead)
-from flaskbb.forum.forms import QuickreplyForm, ReplyForm, NewTopicForm
+from flaskbb.forum.forms import (QuickreplyForm, ReplyForm, NewTopicForm,
+                                 ReportForm)
 from flaskbb.utils.helpers import get_forums
 from flaskbb.user.models import User
 
@@ -366,6 +367,19 @@ def delete_post(post_id):
     return redirect(url_for('forum.view_topic', topic_id=topic_id))
 
 
+@forum.route("/post/<int:post_id>/report", methods=["GET", "POST"])
+@login_required
+def report_post(post_id):
+    post = Post.query.filter_by(id=post_id).first_or_404()
+
+    form = ReportForm()
+    if form.validate_on_submit():
+        form.save(current_user, post)
+        flash("Thanks for reporting!", "success")
+
+    return render_template("forum/report_post.html", form=form)
+
+
 @forum.route("/markread")
 @forum.route("/<int:forum_id>/markread")
 def markread(forum_id=None):

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

@@ -11,6 +11,7 @@
                 {{ navlink('admin.users', 'Users') }}
                 {{ navlink('admin.groups', 'Groups') }}
                 {{ navlink('admin.forums', 'Forums') }}
+                {{ navlink('admin.unread_reports', 'Reports') }}
             </ul>
         </div><!--/.sidebar -->
     </div><!--/.col-sm-3 -->

+ 39 - 0
flaskbb/templates/admin/reports.html

@@ -0,0 +1,39 @@
+{% extends theme("admin/admin_layout.html") %}
+{% block admin_content %}
+{% from theme('macros.html') import render_pagination %}
+
+<legend>Manage Reports | <a href="{{ url_for('admin.unread_reports') }}">Unread Reports</a></legend>
+
+<div class="pull-left" style="padding-bottom: 10px">
+    {{ render_pagination(reports, url_for('admin.reports')) }}
+</div>
+
+<table class="table table-bordered">
+    <thead>
+        <tr>
+            <th>#</th>
+            <th>Poster</th>
+            <th>Topic</th>
+            <th>Reporter</th>
+            <th>Reason</th>
+            <th>Reported</th>
+        </tr>
+    </thead>
+    <tbody>
+        {% for report in reports.items %}
+        <tr>
+            <td>{{ report.id }}</td>
+            <td>{{ report.post.user.username }}</td>
+            <td>{{ report.post.topic.title }}</td>
+            <td>{{ report.reporter.username }}</td>
+            <td>{{ report.reason }}</td>
+            <td>{{ report.reported|time_since }}</td>
+        </tr>
+        {% else %}
+        <tr>
+            <td colspan="6">No reports.</td>
+        </tr>
+        {% endfor %}
+    </tbody>
+</table>
+{% endblock %}

+ 43 - 0
flaskbb/templates/admin/unread_reports.html

@@ -0,0 +1,43 @@
+{% extends theme("admin/admin_layout.html") %}
+{% block admin_content %}
+{% from theme('macros.html') import render_pagination %}
+
+<legend>Manage Reports | <a href="{{ url_for('admin.reports') }}">All Reports</a></legend>
+
+<div class="pull-left" style="padding-bottom: 10px">
+    {{ render_pagination(reports, url_for('admin.unread_reports')) }}
+</div>
+
+<table class="table table-bordered">
+    <thead>
+        <tr>
+            <th>#</th>
+            <th>Poster</th>
+            <th>Topic</th>
+            <th>Reporter</th>
+            <th>Reason</th>
+            <th>Reported</th>
+            <th><a href="{{ url_for('admin.report_markread') }}">Mark all as Read</a></th>
+        </tr>
+    </thead>
+    <tbody>
+        {% for report in reports.items %}
+        <tr>
+            <td>{{ report.id }}</td>
+            <td>{{ report.post.user.username }}</td>
+            <td>{{ report.post.topic.title }}</td>
+            <td>{{ report.reporter.username }}</td>
+            <td>{{ report.reason }}</td>
+            <td>{{ report.reported|time_since }}</td>
+            <td>
+                <a href="{{ url_for('admin.report_markread', report_id=report.id) }}">Mark as Read</a>
+            </td>
+        </tr>
+        {% else %}
+        <tr>
+            <td colspan="7">No unread reports.</td>
+        </tr>
+        {% endfor %}
+    </tbody>
+</table>
+{% endblock %}

+ 1 - 1
flaskbb/templates/forum/forum.html

@@ -22,7 +22,7 @@
             <span class="fa fa-check"></span> Mark as Read
         </a>
 
-        {% if forum.locked %}
+        {% if forum[0].locked %}
         <span class="btn btn-primary">
             <span class="fa fa-lock"></span> Locked
         </span>

+ 16 - 0
flaskbb/templates/forum/report_post.html

@@ -0,0 +1,16 @@
+{% set page_title = "Report Post" %}
+
+{% extends theme("layout.html") %}
+{% block content %}
+{% from theme("macros.html") import render_field %}
+
+<form class="form" role="form" method="post">
+    {{ form.hidden_tag() }}
+    <h3>Report Post</h3>
+
+    {{ render_field(form.reason) }}
+
+    <button type="submit" class="btn btn-success">Report</button>
+    <a class="btn btn-info" href="#" onclick="window.close();return false;">Close</a>
+</form>
+{% endblock %}

+ 3 - 0
flaskbb/templates/forum/topic.html

@@ -152,6 +152,9 @@
                 </span>
 
                 <span class="pull-right">
+                    <a href="{{ url_for('forum.report_post', post_id=post.id) }}" onclick="window.open(this.href, 'wio_window','width=500,height=500'); return false;">
+                        Report
+                    </a> |
                     {% if current_user|edit_post(post.user_id, topic.forum) %}
                     <a href="{{ url_for('forum.edit_post', post_id=post.id) }}">Edit</a> |
                     {% endif %}