This is the first stage of my project of implenting admin/moderator functiona-
lity. At this point, I have finished all the of basic work with the models! I still need to do some tightening of their documentation, but they seem to be working well. Working with Models ======================================== --\ mediagoblin/db/models.py --| Added in the Report model and table. This model is strictly a parent ----| Added in the CommentReport model which holds information about a report | filed against a comment. This class inherits from Report. ----| Added in the MediaReport model which holds information about a report f- | -iled against a media entry. This class inherits from Report. --| Added in a UserBan model and table. This model is in a one to one relatio- | -nship with User. This object acts as a marker for whether a user is banned | or not. --| Added in a Group model. These objects are in a many-to-many relationship | with User to explain which privileges a User has. ----| Added in GroupUserAssociation which is a table used to hold this many to | many relationship between Group & User. --\ mediagoblin/db/migrations.py --| Added in the migrations for all of the additions to models --| Added UserBan_v0 --| Added Report_v0 ----| Added CommentReport_v0 ----| Added MediaReport_v0 --| Added Group_v0 ----| Added GroupUserAssociation_v0 Working with Templates, Views, and Routing =============================================== >>> Reporting a Comment or a MediaEntry --\ mediagoblin/user_pages/views.py --| Added in the function file_a_report to allow user to file reports against | MediaEntries or Comments. Handles GET and POST requests. --| Added in the function file_a_comment_report which uses file_a_report but | also catches appropriate information for comment_ids. I may be able to do | this more eloquently with decorators. --\ mediagoblin/user_pages/routing.py --| Added in route 'mediagoblin.user_pages.media_home.report_media' | (linked to address /u/<user>/m/<media>/report/ ) --| Added in route ''mediagoblin.user_pages.media_home.report_comment' | (linked to address /u/<user>/m/<media>/c/<comment>/report/ ) --\ mediagoblin/templates/mediagoblin/user_pages/report.html --| I created this file to handle the filing of a report. --\ mediagoblin/templates/mediagoblin/user_pages/media.html --| Modified this file to add in links allowing users to report either media | or comments. --\ mediagoblin/user_pages/lib.py --| Added in build_report_form which processes data as either a CommentReport or | a MediaReport depending on which parameters are present --\ mediagoblin/user_pages/forms.py --| Added in CommentReportForm --| Added in MediaReportForm --| note: ReportForm is vestigial to an earlier strategy I used and I'll remove it | promptly --\ mediagoblin/decorators.py --| Added in 'get_media_comment_by_id' for use in mediagoblin/user_pages/views.py >>> New Admin Panels --\ mediagoblin/admin/views.py --| Added in the function admin_users_panel --| Added in the function admin_reports_panel --\ mediagoblin/admin/routing.py --| Added in route 'mediagoblin.admin.users' | (linked to address '/a/users') --| Added in route 'mediagoblin.admin.reports' | (linked to address '/a/reports/') --\ mediagoblin/templates/admin/user.html --| Created this file as a template for monitoring users --\ mediagoblin/templates/admin/report.html --| Created this file as a template for monitoring reports filed against media or | comments
This commit is contained in:
parent
25aad338d4
commit
30a9fe7c1c
@ -17,4 +17,10 @@
|
||||
admin_routes = [
|
||||
('mediagoblin.admin.panel',
|
||||
'/panel',
|
||||
'mediagoblin.admin.views:admin_processing_panel')]
|
||||
'mediagoblin.admin.views:admin_processing_panel'),
|
||||
('mediagoblin.admin.users',
|
||||
'/users',
|
||||
'mediagoblin.admin.views:admin_users_panel'),
|
||||
('mediagoblin.admin.reports',
|
||||
'/reports',
|
||||
'mediagoblin.admin.views:admin_reports_panel')]
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
||||
from mediagoblin.db.models import MediaEntry
|
||||
from mediagoblin.db.models import MediaEntry, User, MediaComment, CommentReport, ReportBase
|
||||
from mediagoblin.decorators import require_active_login
|
||||
from mediagoblin.tools.response import render_to_response
|
||||
|
||||
@ -46,3 +46,40 @@ def admin_processing_panel(request):
|
||||
{'processing_entries': processing_entries,
|
||||
'failed_entries': failed_entries,
|
||||
'processed_entries': processed_entries})
|
||||
|
||||
@require_active_login
|
||||
def admin_users_panel(request):
|
||||
'''
|
||||
Show the global processing panel for this instance
|
||||
'''
|
||||
# TODO: Why not a "require_admin_login" decorator throwing a 403 exception?
|
||||
if not request.user.is_admin:
|
||||
raise Forbidden()
|
||||
|
||||
user_list = User.query
|
||||
|
||||
# Render to response
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/admin/user.html',
|
||||
{'user_list': user_list})
|
||||
|
||||
@require_active_login
|
||||
def admin_reports_panel(request):
|
||||
'''
|
||||
Show the global processing panel for this instance
|
||||
'''
|
||||
# TODO: Why not a "require_admin_login" decorator throwing a 403 exception?
|
||||
if not request.user.is_admin:
|
||||
raise Forbidden()
|
||||
|
||||
report_list = ReportBase.query.filter(ReportBase.resolved==None).order_by(ReportBase.created.desc()).limit(10)
|
||||
closed_report_list = ReportBase.query.filter(ReportBase.resolved!=None).order_by(ReportBase.created.desc()).limit(10)
|
||||
|
||||
# Render to response
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/admin/report.html',
|
||||
{'report_list':report_list,
|
||||
'closed_report_list':closed_report_list})
|
||||
|
||||
|
@ -26,7 +26,7 @@ from sqlalchemy.sql import and_
|
||||
from migrate.changeset.constraint import UniqueConstraint
|
||||
|
||||
from mediagoblin.db.migration_tools import RegisterMigration, inspect_table
|
||||
from mediagoblin.db.models import MediaEntry, Collection, User
|
||||
from mediagoblin.db.models import MediaEntry, Collection, User, MediaComment, Group
|
||||
|
||||
MIGRATIONS = {}
|
||||
|
||||
@ -287,3 +287,70 @@ def unique_collections_slug(db):
|
||||
constraint.create()
|
||||
|
||||
db.commit()
|
||||
|
||||
class ReportBase_v0(declarative_base()):
|
||||
"""
|
||||
|
||||
"""
|
||||
__tablename__ = 'core__reports'
|
||||
id = Column(Integer, primary_key=True)
|
||||
reporter_id = Column(Integer, ForeignKey(User.id), nullable=False)
|
||||
report_content = Column(UnicodeText)
|
||||
created = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||
resolved = Column(DateTime)
|
||||
discriminator = Column('type', Unicode(50))
|
||||
__mapper_args__ = {'polymorphic_on': discriminator}
|
||||
|
||||
|
||||
class CommentReport_v0(ReportBase_v0):
|
||||
__tablename__ = 'core__reports_on_comments'
|
||||
__mapper_args__ = {'polymorphic_identity': 'comment_report'}
|
||||
|
||||
id = Column('id',Integer, ForeignKey('core__reports.id'),
|
||||
primary_key=True)
|
||||
comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=False)
|
||||
|
||||
class MediaReport_v0(ReportBase_v0):
|
||||
__tablename__ = 'core__reports_on_media'
|
||||
__mapper_args__ = {'polymorphic_identity': 'media_report'}
|
||||
|
||||
id = Column('id',Integer, ForeignKey('core__reports.id'),
|
||||
primary_key=True)
|
||||
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
|
||||
|
||||
@RegisterMigration(11, MIGRATIONS)
|
||||
def create_report_tables(db):
|
||||
ReportBase_v0.__table__.create(db.bind)
|
||||
CommentReport_v0.__table__.create(db.bind)
|
||||
MediaReport_v0.__table__.create(db.bind)
|
||||
db.commit()
|
||||
|
||||
class UserBan_v0(declarative_base()):
|
||||
__tablename__ = 'core__user_bans'
|
||||
user_id = Column('id',Integer, ForeignKey(User.id), nullable=False,
|
||||
primary_key=True)
|
||||
expiration_date = Column(DateTime)
|
||||
reason = Column(UnicodeText, nullable=False)
|
||||
|
||||
class Group_v0(declarative_base()):
|
||||
__tablename__ = 'core__groups'
|
||||
id = Column(Integer, nullable=False, primary_key=True)
|
||||
group_name = Column(Unicode, nullable=False)
|
||||
|
||||
class GroupUserAssociation_v0(declarative_base()):
|
||||
__tablename__ = 'core__group_user_associations'
|
||||
|
||||
group_id = Column('core__group_id', Integer, ForeignKey(User.id), primary_key=True)
|
||||
user_id = Column('core__user_id', Integer, ForeignKey(Group.id), primary_key=True)
|
||||
|
||||
|
||||
|
||||
@RegisterMigration(12, MIGRATIONS)
|
||||
def create_banned_and_group_tables(db):
|
||||
UserBan_v0.__table__.create(db.bind)
|
||||
Group_v0.__table__.create(db.bind)
|
||||
GroupUserAssociation_v0.__table__.create(db.bind)
|
||||
db.commit()
|
||||
|
||||
|
||||
|
||||
|
@ -29,6 +29,7 @@ from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
from sqlalchemy.sql.expression import desc
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.util import memoized_property
|
||||
from sqlalchemy.schema import Table
|
||||
|
||||
from mediagoblin.db.extratypes import PathTupleWithSlashes, JSONEncoded
|
||||
from mediagoblin.db.base import Base, DictReadAttrProxy
|
||||
@ -484,10 +485,93 @@ class ProcessingMetaData(Base):
|
||||
return DictReadAttrProxy(self)
|
||||
|
||||
|
||||
class ReportBase(Base):
|
||||
"""
|
||||
|
||||
"""
|
||||
__tablename__ = 'core__reports'
|
||||
id = Column(Integer, primary_key=True)
|
||||
reporter_id = Column(Integer, ForeignKey(User.id), nullable=False)
|
||||
reporter = relationship(User, backref=backref("reports_filed_by",
|
||||
lazy="dynamic",
|
||||
cascade="all, delete-orphan"))
|
||||
report_content = Column(UnicodeText)
|
||||
created = Column(DateTime, nullable=False, default=datetime.datetime.now())
|
||||
resolved = Column(DateTime)
|
||||
discriminator = Column('type', Unicode(50))
|
||||
__mapper_args__ = {'polymorphic_on': discriminator}
|
||||
|
||||
|
||||
class CommentReport(ReportBase):
|
||||
"""
|
||||
A class to keep track of reports that have been filed on comments
|
||||
"""
|
||||
__tablename__ = 'core__reports_on_comments'
|
||||
__mapper_args__ = {'polymorphic_identity': 'comment_report'}
|
||||
|
||||
id = Column('id',Integer, ForeignKey('core__reports.id'),
|
||||
primary_key=True)
|
||||
comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=False)
|
||||
comment = relationship(MediaComment, backref=backref("reports_filed_on",
|
||||
lazy="dynamic",
|
||||
cascade="all, delete-orphan"))
|
||||
|
||||
class MediaReport(ReportBase):
|
||||
"""
|
||||
A class to keep track of reports that have been filed on media entries
|
||||
"""
|
||||
__tablename__ = 'core__reports_on_media'
|
||||
__mapper_args__ = {'polymorphic_identity': 'media_report'}
|
||||
|
||||
id = Column('id',Integer, ForeignKey('core__reports.id'),
|
||||
primary_key=True)
|
||||
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
|
||||
media_entry = relationship(MediaEntry, backref=backref("reports_filed_on",
|
||||
lazy="dynamic",
|
||||
cascade="all, delete-orphan"))
|
||||
|
||||
class UserBan(Base):
|
||||
"""
|
||||
Holds the information on a specific user's ban-state. As long as one of these
|
||||
is attached to a user, they are banned from accessing mediagoblin. When they
|
||||
try to log in, they are greeted with a page that tells them the reason why
|
||||
they are banned and when (if ever) the ban will be lifted
|
||||
:param user_id Holds the id of the user this object is attached to.
|
||||
This should be a one-to-one relationship.
|
||||
:param expiration_date Holds the date that the ban will be lifted. If this
|
||||
is null, the ban is permanent unless a moderator
|
||||
manually lifts it.
|
||||
:param reason Holds the reason why the user was banned.
|
||||
"""
|
||||
__tablename__ = 'core__user_bans'
|
||||
|
||||
user_id = Column('id',Integer, ForeignKey(User.id), nullable=False,
|
||||
primary_key=True)
|
||||
expiration_date = Column(DateTime)
|
||||
reason = Column(UnicodeText, nullable=False)
|
||||
|
||||
|
||||
class Group(Base):
|
||||
__tablename__ = 'core__groups'
|
||||
|
||||
id = Column(Integer, nullable=False, primary_key=True)
|
||||
group_name = Column(Unicode, nullable=False)
|
||||
all_users = relationship(User, backref='all_groups', secondary="core__group_user_associations")
|
||||
|
||||
def __repr__(self):
|
||||
return "<Group %s>" % (self.group_name)
|
||||
|
||||
class GroupUserAssociation(Base):
|
||||
__tablename__ = 'core__group_user_associations'
|
||||
|
||||
group_id = Column('core__group_id', Integer, ForeignKey(User.id), primary_key=True)
|
||||
user_id = Column('core__user_id', Integer, ForeignKey(Group.id), primary_key=True)
|
||||
|
||||
|
||||
|
||||
MODELS = [
|
||||
User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames,
|
||||
MediaAttachmentFile, ProcessingMetaData]
|
||||
|
||||
MediaAttachmentFile, ProcessingMetaData, CommentReport, MediaReport, UserBan, Group, GroupUserAssociation]
|
||||
|
||||
######################################################
|
||||
# Special, migrations-tracking table
|
||||
|
@ -21,7 +21,7 @@ from werkzeug.exceptions import Forbidden, NotFound
|
||||
from werkzeug.urls import url_quote
|
||||
|
||||
from mediagoblin import mg_globals as mgg
|
||||
from mediagoblin.db.models import MediaEntry, User
|
||||
from mediagoblin.db.models import MediaEntry, User, MediaComment
|
||||
from mediagoblin.tools.response import redirect, render_404
|
||||
|
||||
|
||||
@ -226,6 +226,24 @@ def get_media_entry_by_id(controller):
|
||||
return wrapper
|
||||
|
||||
|
||||
def get_media_comment_by_id(controller):
|
||||
"""
|
||||
Pass in a MediaComment based off of a url component
|
||||
"""
|
||||
@wraps(controller)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
comment = MediaComment.query.filter_by(
|
||||
id=request.matchdict['comment']).first()
|
||||
# Still no media? Okay, 404.
|
||||
if not comment:
|
||||
return render_404(request)
|
||||
|
||||
return controller(request, comment=comment, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
||||
def get_workbench(func):
|
||||
"""Decorator, passing in a workbench as kwarg which is cleaned up afterwards"""
|
||||
|
||||
|
95
mediagoblin/templates/mediagoblin/admin/report.html
Normal file
95
mediagoblin/templates/mediagoblin/admin/report.html
Normal file
@ -0,0 +1,95 @@
|
||||
{#
|
||||
# GNU MediaGoblin -- federated, autonomous media hosting
|
||||
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{% extends "mediagoblin/base.html" %}
|
||||
|
||||
{% block title -%}
|
||||
{% trans %}Report panel{% endtrans %} — {{ super() }}
|
||||
{%- endblock %}
|
||||
|
||||
{% block mediagoblin_content %}
|
||||
|
||||
<h1>{% trans %}Report panel{% endtrans %}</h1>
|
||||
|
||||
<p>
|
||||
{% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
|
||||
</p>
|
||||
|
||||
<h2>{% trans %}Reports Filed on Comments{% endtrans %}</h2>
|
||||
|
||||
{% if report_list.count() %}
|
||||
<table class="media_panel processing">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Report Type</th>
|
||||
<th>Offender</th>
|
||||
<th>When Reported</th>
|
||||
<th>Reported By</th>
|
||||
<th>Reason</th>
|
||||
<th>Reported Comment or Media Entry</th>
|
||||
</tr>
|
||||
{% for report in report_list %}
|
||||
<tr>
|
||||
{% if report.discriminator == "comment_report" %}
|
||||
<td>{{ report.id }}</td>
|
||||
<td>Comment Report</td>
|
||||
<td>{{ report.comment.get_author.username }}</td>
|
||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
||||
<td>{{ report.reporter.username }}</td>
|
||||
<td>{{ report.report_content }}</td>
|
||||
<td><a href="{{ report.comment.get_media_entry.url_for_self(request.urlgen) }}">{{ report.comment.get_media_entry.title }}</a></td>
|
||||
{% elif report.discriminator == "media_report" %}
|
||||
<td>{{ report.id }}</td>
|
||||
<td>Media Report</td>
|
||||
<td>{{ report.media_entry.get_uploader.username }}</td>
|
||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
||||
<td>{{ report.reporter.username }}</td>
|
||||
<td>{{ report.report_content[0:20] }}...</td>
|
||||
<td><a href="{{ report.media_entry.url_for_self(request.urlgen) }}">{{ report.media_entry.title }}</a></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<p><em>{% trans %}No open reports found.{% endtrans %}</em></p>
|
||||
{% endif %}
|
||||
<h2>{% trans %}Closed Reports on Comments{% endtrans %}</h2>
|
||||
{% if closed_report_list.count() %}
|
||||
<table class="media_panel processing">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Offender</th>
|
||||
<th>When Reported</th>
|
||||
<th>Reported By</th>
|
||||
<th>Reason</th>
|
||||
<th>Comment Posted On</th>
|
||||
</tr>
|
||||
{% for report in closed_report_list %}
|
||||
<tr>
|
||||
<td>{{ report.id }}</td>
|
||||
<td>{{ report.comment.get_author.username }}</td>
|
||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
||||
<td>{{ report.reporter.username }}</td>
|
||||
<td>{{ report.report_content }}</td>
|
||||
<td><a href="{{ report.comment.get_media_entry.url_for_self(request.urlgen) }}">{{ report.comment.get_media_entry.title }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<p><em>{% trans %}No closed reports found.{% endtrans %}</em></p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
54
mediagoblin/templates/mediagoblin/admin/user.html
Normal file
54
mediagoblin/templates/mediagoblin/admin/user.html
Normal file
@ -0,0 +1,54 @@
|
||||
{#
|
||||
# GNU MediaGoblin -- federated, autonomous media hosting
|
||||
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{% extends "mediagoblin/base.html" %}
|
||||
|
||||
{% block title -%}
|
||||
{% trans %}User panel{% endtrans %} — {{ super() }}
|
||||
{%- endblock %}
|
||||
|
||||
{% block mediagoblin_content %}
|
||||
|
||||
<h1>{% trans %}User panel{% endtrans %}</h1>
|
||||
|
||||
<p>
|
||||
{% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
|
||||
</p>
|
||||
|
||||
<h2>{% trans %}Active Users{% endtrans %}</h2>
|
||||
|
||||
{% if user_list.count() %}
|
||||
<table class="media_panel processing">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Username</th>
|
||||
<th>When Joined</th>
|
||||
<th># of Comments Posted</th>
|
||||
</tr>
|
||||
{% for user in user_list %}
|
||||
<tr>
|
||||
<td>{{ user.id }}</td>
|
||||
<td>{{ user.username }}</td>
|
||||
<td>{{ user.created.strftime("%F %R") }}</td>
|
||||
<td>{{ user.posted_comments.count() }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<p><em>{% trans %}No users found.{% endtrans %}</em></p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
@ -95,6 +95,17 @@
|
||||
{% trans %}Add a comment{% endtrans %}
|
||||
</a>
|
||||
{% endif %}
|
||||
<a
|
||||
{% if not request.user -%}
|
||||
href="{{ request.urlgen('mediagoblin.auth.login') }}"
|
||||
{% else %}
|
||||
href="{{ request.urlgen('mediagoblin.user_pages.media_home.report_media',
|
||||
user=media.get_uploader.username,
|
||||
media=media.slug_or_id) }}"
|
||||
{% endif %}
|
||||
class="button_action" id="button_reportmedia" title="Report media">
|
||||
{% trans %}Report media{% endtrans %}
|
||||
</a>
|
||||
{% if request.user %}
|
||||
<form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment',
|
||||
user= media.get_uploader.username,
|
||||
@ -139,6 +150,17 @@
|
||||
{{ comment.content_html }}
|
||||
{%- endautoescape %}
|
||||
</div>
|
||||
<div>
|
||||
<a {% if not request.user -%}
|
||||
href="{{ request.urlgen('mediagoblin.auth.login') }}"
|
||||
{%- else %}
|
||||
href="{{ request.urlgen('mediagoblin.user_pages.media_home.report_comment',
|
||||
user=media.get_uploader.username,
|
||||
media=media.slug_or_id,
|
||||
comment=comment.id) }}"
|
||||
{%- endif %}>
|
||||
{% trans %} Report {% endtrans %}</a>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
75
mediagoblin/templates/mediagoblin/user_pages/report.html
Normal file
75
mediagoblin/templates/mediagoblin/user_pages/report.html
Normal file
@ -0,0 +1,75 @@
|
||||
{#
|
||||
# GNU MediaGoblin -- federated, autonomous media hosting
|
||||
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{%- extends "mediagoblin/base.html" %}
|
||||
|
||||
{%- block mediagoblin_content %}
|
||||
<h2>File a Report</h2>
|
||||
<form action="" method=POST >
|
||||
{% if comment is defined %}
|
||||
<h4>{% trans %}Reporting this Comment {% endtrans %}</h3>
|
||||
{% set comment_author = comment.get_author %}
|
||||
<div id="comment-{{ comment.id }}"
|
||||
class="comment_wrapper">
|
||||
<div class="comment_author">
|
||||
<img src="{{ request.staticdirect('/images/icon_comment.png') }}" />
|
||||
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
|
||||
user=comment_author.username) }}"
|
||||
class="comment_authorlink">
|
||||
{{- comment_author.username -}}
|
||||
</a>
|
||||
<a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment',
|
||||
comment=comment.id,
|
||||
user=media.get_uploader.username,
|
||||
media=media.slug_or_id) }}#comment"
|
||||
class="comment_whenlink">
|
||||
<span title='{{- comment.created.strftime("%I:%M%p %Y-%m-%d") -}}'>
|
||||
{%- trans formatted_time=timesince(comment.created) -%}
|
||||
{{ formatted_time }} ago
|
||||
{%- endtrans -%}
|
||||
</span></a>:
|
||||
</div>
|
||||
<div class="comment_content">
|
||||
{% autoescape False -%}
|
||||
{{ comment.content_html }}
|
||||
{%- endautoescape %}
|
||||
</div>
|
||||
</div>
|
||||
<input type=hidden name=comment_id value="{{ comment.id }}" />
|
||||
{% elif media is defined %}
|
||||
<h3>{% trans %}Reporting this Media Entry {% endtrans %}</h3>
|
||||
{% trans %}published by {% endtrans %}<a href="{{ request.urlgen('mediagoblin.user_pages.user_home', user=media.get_uploader.username) }}" class="comment_authorlink">{{ media.get_uploader.username }}</a>
|
||||
<div class="media_thumbnail">
|
||||
<a href="request.urlgen('mediagoblin.user_pages.media_home'),
|
||||
user=media.get_uploader.username,
|
||||
media=media.slug_or_id)"><img src="{{ media.thumb_url}}"/></a></td></tr>
|
||||
<a href="request.urlgen('mediagoblin.user_pages.media_home'),
|
||||
user=media.get_uploader.username,
|
||||
media=media.slug_or_id)" class=thumb_entry_title>{{ media.title }}</a>
|
||||
</div>
|
||||
<div class=clear></div>
|
||||
<input type=hidden name=media_entry_id value="{{ media.id }}" />
|
||||
{% endif %}
|
||||
<div class=form_field_input>
|
||||
<label class=form_field_label >{% trans %}Reason for reporting:{% endtrans %}</label>
|
||||
<textarea name=report_reason></textarea>
|
||||
</div>
|
||||
<input type=hidden name=reporter_id value="{{ request.user.id }}" />
|
||||
<input type=submit />
|
||||
{{ csrf_token }}
|
||||
</form>
|
||||
{% endblock %}
|
@ -49,3 +49,19 @@ class MediaCollectForm(wtforms.Form):
|
||||
description=_("""You can use
|
||||
<a href="http://daringfireball.net/projects/markdown/basics">
|
||||
Markdown</a> for formatting."""))
|
||||
|
||||
class CommentReportForm(wtforms.Form):
|
||||
report_reason = wtforms.TextAreaField('Reason for Reporting')
|
||||
comment_id = wtforms.IntegerField()
|
||||
reporter_id = wtforms.IntegerField()
|
||||
|
||||
class MediaReportForm(wtforms.Form):
|
||||
report_reason = wtforms.TextAreaField('Reason for Reporting')
|
||||
media_entry_id = wtforms.IntegerField()
|
||||
reporter_id = wtforms.IntegerField()
|
||||
|
||||
class ReportForm(wtforms.Form):
|
||||
report_reason = wtforms.TextAreaField('Reason for Reporting')
|
||||
media_entry_id = wtforms.IntegerField()
|
||||
reporter_id = wtforms.IntegerField()
|
||||
comment_id = wtforms.IntegerField()
|
||||
|
@ -19,7 +19,8 @@ from mediagoblin.tools.template import render_template
|
||||
from mediagoblin.tools.translate import pass_to_ugettext as _
|
||||
from mediagoblin import mg_globals
|
||||
from mediagoblin.db.base import Session
|
||||
from mediagoblin.db.models import CollectionItem
|
||||
from mediagoblin.db.models import CollectionItem, MediaReport, CommentReport
|
||||
from mediagoblin.user_pages import forms as user_forms
|
||||
|
||||
|
||||
def send_comment_email(user, comment, media, request):
|
||||
@ -75,3 +76,31 @@ def add_media_to_collection(collection, media, note=None, commit=True):
|
||||
|
||||
if commit:
|
||||
Session.commit()
|
||||
|
||||
def build_report_form(form_dict):
|
||||
"""
|
||||
:param form_dict should be an ImmutableMultiDict object which is what is
|
||||
returned from 'request.form.' The Object should have valid keys
|
||||
matching the fields in either MediaReportForm or CommentReportForm
|
||||
|
||||
:returns either of MediaReport or a CommentReport object that has not been saved.
|
||||
In case of an improper form_dict, returns None
|
||||
"""
|
||||
if 'comment_id' in form_dict.keys():
|
||||
report_form = user_forms.CommentReportForm(form_dict)
|
||||
elif 'media_entry_id' in form_dict.keys():
|
||||
report_form = user_forms.MediaReportForm(form_dict)
|
||||
else:
|
||||
return None
|
||||
if report_form.validate() and 'comment_id' in form_dict.keys():
|
||||
report_model = CommentReport()
|
||||
report_model.comment_id = report_form.comment_id.data
|
||||
elif report_form.validate() and 'media_entry_id' in form_dict.keys():
|
||||
report_model = MediaReport()
|
||||
report_model.media_entry_id = report_form.media_entry_id.data
|
||||
else:
|
||||
return None
|
||||
report_model.report_content = report_form.report_reason.data or u''
|
||||
report_model.reporter_id = report_form.reporter_id.data
|
||||
return report_model
|
||||
|
||||
|
@ -23,6 +23,10 @@ add_route('mediagoblin.user_pages.media_home',
|
||||
'/u/<string:user>/m/<string:media>/',
|
||||
'mediagoblin.user_pages.views:media_home')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_home.report_media',
|
||||
'/u/<string:user>/m/<string:media>/report/',
|
||||
'mediagoblin.user_pages.views:file_a_report')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_confirm_delete',
|
||||
'/u/<string:user>/m/<int:media_id>/confirm-delete/',
|
||||
'mediagoblin.user_pages.views:media_confirm_delete')
|
||||
@ -40,6 +44,10 @@ add_route('mediagoblin.user_pages.media_home.view_comment',
|
||||
'/u/<string:user>/m/<string:media>/c/<int:comment>/',
|
||||
'mediagoblin.user_pages.views:media_home')
|
||||
|
||||
add_route('mediagoblin.user_pages.media_home.report_comment',
|
||||
'/u/<string:user>/m/<string:media>/c/<int:comment>/report/',
|
||||
'mediagoblin.user_pages.views:file_a_comment_report')
|
||||
|
||||
# User's tags gallery
|
||||
add_route('mediagoblin.user_pages.user_tag_gallery',
|
||||
'/u/<string:user>/tag/<string:tag>/',
|
||||
|
@ -19,19 +19,21 @@ import datetime
|
||||
|
||||
from mediagoblin import messages, mg_globals
|
||||
from mediagoblin.db.models import (MediaEntry, MediaTag, Collection,
|
||||
CollectionItem, User)
|
||||
CollectionItem, User, MediaComment,
|
||||
CommentReport, MediaReport)
|
||||
from mediagoblin.tools.response import render_to_response, render_404, \
|
||||
redirect, redirect_obj
|
||||
from mediagoblin.tools.translate import pass_to_ugettext as _
|
||||
from mediagoblin.tools.pagination import Pagination
|
||||
from mediagoblin.user_pages import forms as user_forms
|
||||
from mediagoblin.user_pages.lib import (send_comment_email,
|
||||
from mediagoblin.user_pages.lib import (send_comment_email, build_report_form,
|
||||
add_media_to_collection)
|
||||
|
||||
from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
|
||||
get_media_entry_by_id,
|
||||
require_active_login, user_may_delete_media, user_may_alter_collection,
|
||||
get_user_collection, get_user_collection_item, active_user_from_url)
|
||||
get_user_collection, get_user_collection_item, active_user_from_url,
|
||||
get_media_comment_by_id)
|
||||
|
||||
from werkzeug.contrib.atom import AtomFeed
|
||||
|
||||
@ -616,3 +618,28 @@ def processing_panel(request):
|
||||
'processing_entries': processing_entries,
|
||||
'failed_entries': failed_entries,
|
||||
'processed_entries': processed_entries})
|
||||
|
||||
@require_active_login
|
||||
@get_user_media_entry
|
||||
def file_a_report(request, media, comment=None):
|
||||
if request.method == "POST":
|
||||
report_form = build_report_form(request.form)
|
||||
report_form.save()
|
||||
return redirect(
|
||||
request,
|
||||
'index')
|
||||
if comment is not None:
|
||||
context = {'media': media,
|
||||
'comment':comment}
|
||||
else:
|
||||
context = {'media': media}
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/user_pages/report.html',
|
||||
context)
|
||||
|
||||
@require_active_login
|
||||
@get_user_media_entry
|
||||
@get_media_comment_by_id
|
||||
def file_a_comment_report(request, media, comment):
|
||||
return file_a_report(request, comment=comment)
|
||||
|
Loading…
x
Reference in New Issue
Block a user