diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 3e6791c4..247298ac 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -299,8 +299,6 @@ class ReportBase_v0(declarative_base()):
report_content = Column(UnicodeText)
reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False)
created = Column(DateTime, nullable=False, default=datetime.datetime.now)
- resolved = Column(DateTime)
- result = Column(UnicodeText)
discriminator = Column('type', Unicode(50))
__mapper_args__ = {'polymorphic_on': discriminator}
@@ -317,13 +315,20 @@ 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)
+ id = Column('id',Integer, ForeignKey('core__reports.id'), primary_key=True)
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
+class ArchivedReport_v0(ReportBase_v0):
+ __tablename__ = 'core__reports_archived'
+ __mapper_args__ = {'polymorphic_identity': 'archived_report'}
+
+ id = Column('id',Integer, ForeignKey('core__reports.id'))
+
+ media_entry_id = Column(Integer, ForeignKey(MediaEntry.id))
+ comment_id = Column(Integer, ForeignKey(MediaComment.id))
+ resolver_id = Column(Integer, ForeignKey(User.id), nullable=False)
+ resolved_time = Column(DateTime)
+ result = Column(UnicodeText)
class UserBan_v0(declarative_base()):
__tablename__ = 'core__user_bans'
@@ -356,6 +361,7 @@ def create_moderation_tables(db):
ReportBase_v0.__table__.create(db.bind)
CommentReport_v0.__table__.create(db.bind)
MediaReport_v0.__table__.create(db.bind)
+ ArchivedReport_v0.__table__.create(db.bind)
UserBan_v0.__table__.create(db.bind)
Privilege_v0.__table__.create(db.bind)
PrivilegeUserAssociation_v0.__table__.create(db.bind)
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 01078db8..c85d546f 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -515,11 +515,18 @@ class ReportBase(Base):
cascade="all, delete-orphan"),
primaryjoin="User.id==ReportBase.reported_user_id")
created = Column(DateTime, nullable=False, default=datetime.datetime.now())
- resolved = Column(DateTime)
- result = Column(UnicodeText)
discriminator = Column('type', Unicode(50))
__mapper_args__ = {'polymorphic_on': discriminator}
+ def is_comment_report(self):
+ return self.discriminator=='comment_report'
+
+ def is_media_entry_report(self):
+ return self.discriminator=='media_report'
+
+ def is_archived_report(self):
+ return self.discriminator=='archived_report'
+
class CommentReport(ReportBase):
"""
@@ -548,10 +555,40 @@ class MediaReport(ReportBase):
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
media_entry = relationship(
MediaEntry,
- backref=backref("reports_filed_on",
+ backref=backref("reports_filed_onmod/reports/1/",
lazy="dynamic",
cascade="all, delete-orphan"))
+class ArchivedReport(ReportBase):
+ """
+ A table to keep track of reports that have been resolved
+ """
+ __tablename__ = 'core__reports_archived'
+ __mapper_args__ = {'polymorphic_identity': 'archived_report'}
+ id = Column('id',Integer, ForeignKey('core__reports.id'),
+ primary_key=True)
+
+ media_entry_id = Column(Integer, ForeignKey(MediaEntry.id))
+ media_entry = relationship(
+ MediaEntry,
+ backref=backref("past_reports_filed_on",
+ lazy="dynamic"))
+ comment_id = Column(Integer, ForeignKey(MediaComment.id))
+ comment = relationship(
+ MediaComment, backref=backref("past_reports_filed_on",
+ lazy="dynamic"))
+
+ resolver_id = Column(Integer, ForeignKey(User.id), nullable=False)
+ resolver = relationship(
+ User,
+ backref=backref("reports_resolved_by",
+ lazy="dynamic",
+ cascade="all, delete-orphan"),
+ primaryjoin="User.id==ArchivedReport.resolver_id")
+
+ resolved = Column(DateTime)
+ result = Column(UnicodeText)
+
class UserBan(Base):
"""
Holds the information on a specific user's ban-state. As long as one of
@@ -641,7 +678,8 @@ privilege_foundations = [[u'admin'], [u'moderator'], [u'uploader'],[u'reporter']
MODELS = [
User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData, ReportBase,
- CommentReport, MediaReport, UserBan, Privilege, PrivilegeUserAssociation]
+ CommentReport, MediaReport, UserBan, Privilege, PrivilegeUserAssociation,
+ ArchivedReport]
# Foundations are the default rows that are created immediately after the tables are initialized. Each entry to
# this dictionary should be in the format of
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 6ffec44d..1aa0a63c 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -15,7 +15,8 @@
# along with this program. If not, see
%s took away %s\'s %s privileges" % (
+ request.user.username,
+ user.username,
+ privilege.privilege_name)
+ user.all_privileges.remove(privilege)
+
+ # If the moderator elects to ban the user, a new instance of user_ban
+ # will be created.
+ if u'userban' in form.action_to_resolve.data:
+ reason = form.resolution_content.data + \
+ "
"+request.user.username
+ user_ban = UserBan(
+ user_id=form.targeted_user.data,
+ expiration_date=form.user_banned_until.data,
+ reason= form.why_user_was_banned.data
+ )
+ Session.add(user_ban)
+
+ if form.user_banned_until.data is not None:
+ form.resolution_content.data += \
+ u"
%s banned user %s until %s." % (
+ request.user.username,
+ user.username,
+ form.user_banned_until.data)
+ else:
+ form.resolution_content.data += \
+ u"
%s banned user %s indefinitely." % (
+ request.user.username,
+ user.username)
+
+ # If the moderator elects to send a warning message. An email will be
+ # sent to the email address given at sign up
+ if u'sendmessage' in form.action_to_resolve.data:
+ message_body = form.message_to_user.data
+ form.resolution_content.data += \
+ u"
%s sent a warning email to the offender." % (
+ request.user.username)
+
+ archive = ArchivedReport(
+ reporter_id=report.reporter_id,
+ report_content=report.report_content,
+ reported_user_id=report.reported_user_id,
+ created=report.created,
+ resolved=datetime.now(),
+ resolver_id=request.user.id
+ )
+
+ if u'delete' in form.action_to_resolve.data and \
+ report.is_comment_report():
+ deleted_comment = report.comment
+ Session.delete(deleted_comment)
+ form.resolution_content.data += \
+ u"
%s deleted the comment" % (
+ request.user.username)
+ elif u'delete' in form.action_to_resolve.data and \
+ report.is_media_entry_report():
+ deleted_media = report.media_entry
+ Session.delete(deleted_media)
+ form.resolution_content.data += \
+ u"
%s deleted the media entry" % (
+ request.user.username)
+
+ # If the moderator didn't delete the content we then attach the
+ # content to the archived report. We also have to actively delete the
+ # old report, since it won't be deleted by cascading.
+ elif report.is_comment_report():
+ archive.comment_id = report.comment_id
+ Session.delete(report)
+ elif report.is_media_entry_report():
+ archive.media_entry_id = report.media_entry.id
+ Session.delete(report)
+
+
+ archive.result=form.resolution_content.data
+# Session.add(archive)
+ Session.commit()
+ if message_body:
+ send_email(
+ mg_globals.app_config['email_sender_address'],
+ [user.email],
+ _('Warning from')+ '- {moderator} '.format(
+ moderator=request.user.username),
+ message_body)
+
+ return redirect(
+ request,
+ 'mediagoblin.moderation.users_detail',
+ user=user.username)
+ except:
+#TODO make a more effective and specific try except statement. To account for
+# incorrect value addition my moderators
+ print sys.exc_info()[0]
+ print sys.exc_info()[1]
+ traceback.print_tb(sys.exc_info()[2])
+ Session.rollback()
+ return redirect(
+ request,
+ 'mediagoblin.moderation.reports_detail',
+ report_id=report.id)
diff --git a/mediagoblin/moderation/views.py b/mediagoblin/moderation/views.py
index 6f6318bc..67928927 100644
--- a/mediagoblin/moderation/views.py
+++ b/mediagoblin/moderation/views.py
@@ -18,11 +18,13 @@ from werkzeug.exceptions import Forbidden
from mediagoblin.db.models import (MediaEntry, User, MediaComment, \
CommentReport, ReportBase, Privilege, \
- UserBan)
+ UserBan, ArchivedReport)
+from mediagoblin.db.util import user_privileges_to_dictionary
from mediagoblin.decorators import (require_admin_or_moderator_login, \
active_user_from_url)
from mediagoblin.tools.response import render_to_response, redirect
from mediagoblin.moderation import forms as moderation_forms
+from mediagoblin.moderation.tools import take_punitive_actions
from datetime import datetime
@require_admin_or_moderator_login
@@ -67,17 +69,22 @@ def moderation_users_detail(request):
'''
user = User.query.filter_by(username=request.matchdict['user']).first()
active_reports = user.reports_filed_on.filter(
- ReportBase.resolved==None).limit(5)
+ ReportBase.discriminator!='archived_report').limit(5)
closed_reports = user.reports_filed_on.filter(
- ReportBase.resolved!=None).all()
+ ReportBase.discriminator=='archived_report').all()
privileges = Privilege.query
+ user_banned = UserBan.query.get(user.id)
+ user_privileges = user_privileges_to_dictionary(user.id)
+ requesting_user_privileges = user_privileges_to_dictionary(request.user.id)
return render_to_response(
request,
'mediagoblin/moderation/user.html',
{'user':user,
- 'privileges':privileges,
- 'reports':active_reports})
+ 'privileges': privileges,
+ 'requesting_user_privileges':requesting_user_privileges,
+ 'reports':active_reports,
+ 'user_banned':user_banned})
@require_admin_or_moderator_login
def moderation_reports_panel(request):
@@ -86,10 +93,10 @@ def moderation_reports_panel(request):
media entries for this instance.
'''
report_list = ReportBase.query.filter(
- ReportBase.resolved==None).order_by(
+ ReportBase.discriminator!="archived_report").order_by(
ReportBase.created.desc()).limit(10)
closed_report_list = ReportBase.query.filter(
- ReportBase.resolved!=None).order_by(
+ ReportBase.discriminator=="archived_report").order_by(
ReportBase.created.desc()).limit(10)
# Render to response
@@ -109,66 +116,12 @@ def moderation_reports_detail(request):
form = moderation_forms.ReportResolutionForm(request.form)
report = ReportBase.query.get(request.matchdict['report_id'])
+ form.take_away_privileges.choices = [(s.privilege_name,s.privilege_name.title()) for s in report.reported_user.all_privileges]
+
if request.method == "POST" and form.validate():
user = User.query.get(form.targeted_user.data)
- if form.action_to_resolve.data == u'takeaway':
- if report.discriminator == u'comment_report':
- privilege = Privilege.one({'privilege_name':u'commenter'})
- form.resolution_content.data += \
- u"
%s took away %s\'s commenting privileges" % (
- request.user.username,
- user.username)
- else:
- privilege = Privilege.one({'privilege_name':u'uploader'})
- form.resolution_content.data += \
- u"
%s took away %s\'s media uploading privileges" % (
- request.user.username,
- user.username)
- user.all_privileges.remove(privilege)
- user.save()
- report.result = form.resolution_content.data
- report.resolved = datetime.now()
- report.save()
-
- elif form.action_to_resolve.data == u'userban':
- reason = form.resolution_content.data + \
- "
"+request.user.username
- user_ban = UserBan(
- user_id=form.targeted_user.data,
- expiration_date=form.user_banned_until.data,
- reason= form.resolution_content.data)
- user_ban.save()
- if not form.user_banned_until == "":
- form.resolution_content.data += \
- u"
%s banned user %s until %s." % (
- request.user.username,
- user.username,
- form.user_banned_until.data)
- else:
- form.resolution_content.data += \
- u"
%s banned user %s indefinitely." % (
- request.user.username,
- user.username,
- form.user_banned_until.data)
+ return take_punitive_actions(request, form, report, user)
- report.result = form.resolution_content.data
- report.resolved = datetime.now()
- report.save()
-
- else:
- pass
-
- return redirect(
- request,
- 'mediagoblin.moderation.users_detail',
- user=user.username)
-
- if report.discriminator == 'comment_report':
- comment = MediaComment.query.get(report.comment_id)
- media_entry = None
- elif report.discriminator == 'media_report':
- media_entry = MediaEntry.query.get(report.media_entry_id)
- comment = None
form.targeted_user.data = report.reported_user_id
@@ -176,8 +129,6 @@ def moderation_reports_detail(request):
request,
'mediagoblin/moderation/report.html',
{'report':report,
- 'media_entry':media_entry,
- 'comment':comment,
'form':form})
@require_admin_or_moderator_login
@@ -189,7 +140,7 @@ def give_or_take_away_privilege(request, url_user):
form = moderation_forms.PrivilegeAddRemoveForm(request.form)
if request.method == "POST" and form.validate():
privilege = Privilege.one({'privilege_name':form.privilege_name.data})
- if privilege in url_user.all_privileges is True:
+ if privilege in url_user.all_privileges:
url_user.all_privileges.remove(privilege)
else:
url_user.all_privileges.append(privilege)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 343648d8..0378350e 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -618,6 +618,23 @@ table.admin_panel th, table.admin_side_panel th {
font-weight: bold;
padding-bottom: 4px;
text-align: left;
+ color: #fff;
+}
+
+table td.user_with_privilege {
+ font-weight: bold;
+ color: #86D4B1;
+}
+
+table td.user_without_privilege {
+ font-weight: bold;
+ color: #D486B1;
+}
+
+.return_to_panel {
+ text-align:right;
+ float: right;
+ font-size:1.2em
}
/* Delete panel */
diff --git a/mediagoblin/static/images/icon_clipboard_alert.png b/mediagoblin/static/images/icon_clipboard_alert.png
new file mode 100644
index 00000000..952c588d
Binary files /dev/null and b/mediagoblin/static/images/icon_clipboard_alert.png differ
diff --git a/mediagoblin/templates/mediagoblin/moderation/report.html b/mediagoblin/templates/mediagoblin/moderation/report.html
index 6938569d..44067771 100644
--- a/mediagoblin/templates/mediagoblin/moderation/report.html
+++ b/mediagoblin/templates/mediagoblin/moderation/report.html
@@ -22,9 +22,16 @@
{% if not report %}
Sorry, no such report found.
{% else %}
-
❖ Reported media by + {{ report.reported_user.username }}
+ + {% else %} +