From 6483b37060062ef7c7d40d9ae712c99a7e73775a Mon Sep 17 00:00:00 2001 From: tilly-Q Date: Mon, 23 Sep 2013 13:20:18 -0400 Subject: [PATCH] At this point, I am very close to done with this code! I made one big change at paroneayea's request, which was to make to possible to turn off user's ability to file reports through a mediagoblin.ini setting. Aside from this, I had to make it possible for the Moderation User Panel to display more than 10 users. And aside from that, I just had to fix some errors which cropped up with my most recent additions. I also fixed some tests that were broken because I had changed the checks for whether or not a user is active. Nearing the end! =============================================================================== Made it possible to turn off reports through a mediagoblin.ini setting =============================================================================== --\ mediagoblin.ini --\ mediagoblin/config_spec.ini --\ mediagoblin/decorators.py --\ mediagoblin/moderation/views.py --\ mediagoblin/templates/mediagoblin/user_pages/media.html --\ mediagoblin/user_pages/views.py =============================================================================== Made User Panel capable of showing more than 1 page of users =============================================================================== --\ mediagoblin/moderation/forms.py --\ mediagoblin/moderation/views.py --\ mediagoblin/templates/mediagoblin/moderation/user_panel.html =============================================================================== Fixed Broken Tests =============================================================================== --\ mediagoblin/tests/test_notifications.py --\ mediagoblin/tests/test_openid.py --\ mediagoblin/tests/test_persona.py --\ mediagoblin/tests/test_reporting.py =============================================================================== Fixed errors in code =============================================================================== --\ mediagoblin/db/migrations.py --| Set nullable to True for MediaReports' and CommentReports' content foreign |keys --\ mediagoblin/db/models.py --| Got rid of cascading rules for MediaReports' and CommentReports' content |foreign keys. This makes it possible for the Reports to continue to exist |after the content is deleted. --\ mediagoblin/moderation/tools.py --| Fixed formatting of Report Resolution Methods --| Took out pieces of code used in debugging --\ mediagoblin/templates/mediagoblin/base.html --\ mediagoblin/templates/mediagoblin/moderation/report.html --| Made reports details page able to tell what is a deleted archived report. --\ mediagoblin/templates/mediagoblin/moderation/report_panel.html --\ mediagoblin/templates/mediagoblin/utils/report.html --- mediagoblin.ini | 3 + mediagoblin/config_spec.ini | 3 + mediagoblin/db/migrations.py | 4 +- mediagoblin/db/models.py | 8 +- mediagoblin/decorators.py | 15 ++ mediagoblin/moderation/forms.py | 7 + mediagoblin/moderation/tools.py | 149 ++++++++---------- mediagoblin/moderation/views.py | 23 ++- mediagoblin/templates/mediagoblin/base.html | 13 +- .../mediagoblin/moderation/report.html | 4 +- .../mediagoblin/moderation/report_panel.html | 4 +- .../mediagoblin/moderation/user_panel.html | 36 +++++ .../mediagoblin/user_pages/media.html | 16 +- .../templates/mediagoblin/utils/report.html | 7 +- mediagoblin/tests/test_notifications.py | 3 +- mediagoblin/tests/test_openid.py | 2 +- mediagoblin/tests/test_persona.py | 4 + mediagoblin/tests/test_reporting.py | 5 +- mediagoblin/user_pages/views.py | 4 +- 19 files changed, 188 insertions(+), 122 deletions(-) diff --git a/mediagoblin.ini b/mediagoblin.ini index 30dacadf..874ebcbd 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -20,6 +20,9 @@ email_debug_mode = true # Set to false to disable registrations allow_registration = true +# Set to false to disable the ability for users to report offensive content +allow_reporting = true + ## Uncomment this to put some user-overriding templates here # local_templates = %(here)s/user_dev/templates/ diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 43e1898c..0e224503 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -42,6 +42,9 @@ allow_comments = boolean(default=True) # Whether comments are ascending or descending comments_ascending = boolean(default=True) +# Enable/disable reporting +allow_reporting = boolean(default=True) + # By default not set, but you might want something like: # "%(here)s/user_dev/templates/" local_templates = string() diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2e05bf2a..ff74aa30 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -494,7 +494,7 @@ class CommentReport_v0(ReportBase_v0): id = Column('id',Integer, ForeignKey('core__reports.id'), primary_key=True) - comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=False) + comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=True) @@ -503,7 +503,7 @@ class MediaReport_v0(ReportBase_v0): __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_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=True) class UserBan_v0(declarative_base()): __tablename__ = 'core__user_bans' diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index cec311f2..466f31b8 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -764,8 +764,7 @@ class CommentReport(ReportBase): comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=True) comment = relationship( MediaComment, backref=backref("reports_filed_on", - lazy="dynamic", - cascade="all, delete-orphan")) + lazy="dynamic")) class MediaReport(ReportBase): @@ -782,9 +781,8 @@ class MediaReport(ReportBase): media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=True) media_entry = relationship( MediaEntry, - backref=backref("reports_filed_onmod/reports/1/", - lazy="dynamic", - cascade="all, delete-orphan")) + backref=backref("reports_filed_on", + lazy="dynamic")) class UserBan(Base): """ diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index d5a10db1..d0b5ad33 100644 --- a/mediagoblin/decorators.py +++ b/mediagoblin/decorators.py @@ -304,6 +304,21 @@ def allow_registration(controller): return wrapper +def allow_reporting(controller): + """ Decorator for if reporting is enabled""" + @wraps(controller) + def wrapper(request, *args, **kwargs): + if not mgg.app_config["allow_reporting"]: + messages.add_message( + request, + messages.WARNING, + _('Sorry, reporting is disabled on this instance.')) + return redirect(request, 'index') + + return controller(request, *args, **kwargs) + + return wrapper + def get_optional_media_comment_by_id(controller): """ Pass in a MediaComment based off of a url component. Because of this decor- diff --git a/mediagoblin/moderation/forms.py b/mediagoblin/moderation/forms.py index 78e9fcdc..5582abdd 100644 --- a/mediagoblin/moderation/forms.py +++ b/mediagoblin/moderation/forms.py @@ -139,3 +139,10 @@ class ReportPanelSortingForm(wtforms.Form): validators=[wtforms.validators.optional()]) reporter = wtforms.IntegerField( validators=[wtforms.validators.optional()]) + +class UserPanelSortingForm(wtforms.Form): + """ + This form is used for sorting different reports. + """ + p = wtforms.IntegerField( + validators=[wtforms.validators.optional()]) diff --git a/mediagoblin/moderation/tools.py b/mediagoblin/moderation/tools.py index 109f3d8f..224a0c73 100644 --- a/mediagoblin/moderation/tools.py +++ b/mediagoblin/moderation/tools.py @@ -25,90 +25,79 @@ import sys, traceback def take_punitive_actions(request, form, report, user): message_body ='' - try: - - # The bulk of this action is running through all of the different - # punitive actions that a moderator could take. - if u'takeaway' in form.action_to_resolve.data: - for privilege_name in form.take_away_privileges.data: - take_away_privileges(user.username, privilege_name) - form.resolution_content.data += \ - u"\n{mod} took away {user}\'{privilege} privileges.".format( - mod=request.user.username, - user=user.username, - privilege=privilege_name) - - # 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: - user_ban = ban_user(form.targeted_user.data, - expiration_date=form.user_banned_until.data, - reason=form.why_user_was_banned.data) - Session.add(user_ban) + + # The bulk of this action is running through all of the different + # punitive actions that a moderator could take. + if u'takeaway' in form.action_to_resolve.data: + for privilege_name in form.take_away_privileges.data: + take_away_privileges(user.username, privilege_name) form.resolution_content.data += \ - u"\n{mod} banned user {user} until {expiration_date}.".format( + u"\n{mod} took away {user}\'{privilege} privileges.".format( mod=request.user.username, user=user.username, - expiration_date = ( - "until {date}".format(date=form.user_banned_until.data) - if form.user_banned_until.data - else "indefinitely" - ) - ) - - # 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 + privilege=privilege_name) + + # 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: + user_ban = ban_user(form.targeted_user.data, + expiration_date=form.user_banned_until.data, + reason=form.why_user_was_banned.data) + Session.add(user_ban) + form.resolution_content.data += \ + u"\n{mod} banned user {user} {expiration_date}.".format( + mod=request.user.username, + user=user.username, + expiration_date = ( + "until {date}".format(date=form.user_banned_until.data) + if form.user_banned_until.data + else "indefinitely" + ) + ) + + # 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"\n{mod} sent a warning email to the {user}.".format( + mod=request.user.username, + user=user.username) + + 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"\n{mod} sent a warning email to the {user}.".format( - mod=request.user.username, - user=user.username) - - 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"\n{mod} deleted the comment.".format( - mod=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"\n{mod} deleted the media entry.".format( - mod=request.user.username) - report.archive( - resolver_id=request.user.id, - resolved=datetime.now(), - result=form.resolution_content.data) - - Session.add(report) - 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) + u"\n{mod} deleted the comment.".format( + mod=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"\n{mod} deleted the media entry.".format( + mod=request.user.username) + report.archive( + resolver_id=request.user.id, + resolved=datetime.now(), + result=form.resolution_content.data) + + Session.add(report) + 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) + def take_away_privileges(user,*privileges): """ diff --git a/mediagoblin/moderation/views.py b/mediagoblin/moderation/views.py index 45edff1d..4721834a 100644 --- a/mediagoblin/moderation/views.py +++ b/mediagoblin/moderation/views.py @@ -19,8 +19,9 @@ from werkzeug.exceptions import Forbidden from mediagoblin.db.models import (MediaEntry, User, MediaComment, \ CommentReport, ReportBase, Privilege, \ UserBan) -from mediagoblin.decorators import (require_admin_or_moderator_login, \ - active_user_from_url, user_has_privilege) +from mediagoblin.decorators import (require_admin_or_moderator_login, + active_user_from_url, user_has_privilege, + allow_reporting) 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, \ @@ -58,12 +59,24 @@ def moderation_users_panel(request): ''' Show the global panel for monitoring users in this instance ''' - user_list = User.query + current_page = 1 + if len(request.args) > 0: + form = moderation_forms.UserPanelSortingForm(request.args) + if form.validate(): + current_page = form.p.data or 1 + + all_user_list = User.query + user_list = all_user_list.order_by( + User.created.desc()).offset( + (current_page-1)*10).limit(10) + last_page = int(ceil(all_user_list.count()/10.)) return render_to_response( request, 'mediagoblin/moderation/user_panel.html', - {'user_list': user_list}) + {'user_list': user_list, + 'current_page':current_page, + 'last_page':last_page}) @require_admin_or_moderator_login def moderation_users_detail(request): @@ -89,6 +102,7 @@ def moderation_users_detail(request): 'ban_form':ban_form}) @require_admin_or_moderator_login +@allow_reporting def moderation_reports_panel(request): ''' Show the global panel for monitoring reports filed against comments or @@ -135,6 +149,7 @@ def moderation_reports_panel(request): 'closed_settings':closed_settings}) @require_admin_or_moderator_login +@allow_reporting def moderation_reports_detail(request): """ This is the page an admin or moderator goes to see the details of a report. diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 945d5ee3..94ca7aa5 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -92,11 +92,10 @@ "javascript:;" {% endif %} >{% trans %}log out{% endtrans %} - - {%- trans %}Create new collection{% endtrans -%} -

- Terms of Service + + {%- trans %}Terms of Service{%- endtrans %} +

{% endif %} {%- elif auth %} @@ -141,6 +140,9 @@ {%- trans %}Add media{% endtrans -%} + + {%- trans %}Create new collection{% endtrans -%} + {% if request.user.has_privilege('admin','moderator') %}

Moderation powers: @@ -157,9 +159,6 @@

{% endif %} - - {%- trans %}Create new collection{% endtrans -%} -

Terms of Service

diff --git a/mediagoblin/templates/mediagoblin/moderation/report.html b/mediagoblin/templates/mediagoblin/moderation/report.html index 062ec24a..cb717cde 100644 --- a/mediagoblin/templates/mediagoblin/moderation/report.html +++ b/mediagoblin/templates/mediagoblin/moderation/report.html @@ -30,7 +30,7 @@ title="Return to Reports Panel"> {% trans %}Return to Reports Panel{% endtrans %}

{% trans %}Report{% endtrans %} #{{ report.id }}

- {% if report.comment %} + {% if report.is_comment_report() and report.comment %} {% trans %}Reported comment{% endtrans %}: {% set comment = report.comment %} @@ -62,7 +62,7 @@ {% endautoescape %} - {% elif report.media_entry %} + {% elif report.is_media_entry_report() and report.media_entry %} {% set media_entry = report.media_entry %}
diff --git a/mediagoblin/templates/mediagoblin/moderation/report_panel.html b/mediagoblin/templates/mediagoblin/moderation/report_panel.html index 988dd292..4eb16b2b 100644 --- a/mediagoblin/templates/mediagoblin/moderation/report_panel.html +++ b/mediagoblin/templates/mediagoblin/moderation/report_panel.html @@ -33,6 +33,7 @@

{% trans %}Active Reports Filed{% endtrans %}

+{% if report_list.count() %} {% if not active_settings.last_page == 1 %} {% if 'active_p='~active_settings.current_page in request.query_string %} {% set query_string = request.query_string %}{% else %} @@ -70,7 +71,6 @@ curr_page !=p %} {% endif %}
{% endif %} -{% if report_list.count() %} @@ -121,6 +121,7 @@ curr_page !=p %}

{% trans %}No open reports found.{% endtrans %}

{% endif %}

{% trans %}Closed Reports{% endtrans %}

+{% if closed_report_list.count() %} {% if not closed_settings.last_page == 1 %} {% if 'closed_p='~closed_settings.current_page in request.query_string %} {% set query_string = request.query_string %}{% else %} @@ -161,7 +162,6 @@ curr_page !=p %} {% endif %} {% endif %} -{% if closed_report_list.count() %}
diff --git a/mediagoblin/templates/mediagoblin/moderation/user_panel.html b/mediagoblin/templates/mediagoblin/moderation/user_panel.html index 54ef7c11..4949960e 100644 --- a/mediagoblin/templates/mediagoblin/moderation/user_panel.html +++ b/mediagoblin/templates/mediagoblin/moderation/user_panel.html @@ -34,6 +34,42 @@

{% trans %}Active Users{% endtrans %}

{% if user_list.count() %} + {% if not last_page == 1 %} + {% if 'p='~current_page in request.query_string %} + {% set query_string = request.query_string %}{% else %} + {% set query_string = +'p='~current_page~"&"+request.query_string %} + {% endif %} +
+ {% set first_vis = current_page-3 %} + {% set last_vis = current_page+3 %} + {% if 1 == current_page %}1{% else %} + + 1{% endif %} + {% if first_vis > 1 %}...{% endif %} + {% for p in range(first_vis,last_vis+1) %} + {% if p > 1 and p < last_page and +current_page !=p %} + + {{ p }} + {% elif p > 1 and p < last_page %} + {{ p }} + {% endif %} + {% endfor %} + {% if last_vis < last_page %}...{% endif %} + {% if last_page != current_page %} + + {{ last_page }} + {% else %}{{ last_page }} + {% endif %} +
+ {% endif %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 62c2a48c..81e5013e 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -147,15 +147,13 @@ {%- endautoescape %}
- - {% trans %} Report {% endtrans %} + comment=comment.id) }}"> + {% trans %}Report{% endtrans %} + {% endif %}
{% endfor %} @@ -181,7 +179,9 @@ {% include "mediagoblin/utils/collections.html" %} - {% include "mediagoblin/utils/report.html" %} + {% if app_config.allow_reporting %} + {% include "mediagoblin/utils/report.html" %} + {% endif %} {% include "mediagoblin/utils/license.html" %} diff --git a/mediagoblin/templates/mediagoblin/utils/report.html b/mediagoblin/templates/mediagoblin/utils/report.html index 2fa4f959..3829de97 100644 --- a/mediagoblin/templates/mediagoblin/utils/report.html +++ b/mediagoblin/templates/mediagoblin/utils/report.html @@ -18,14 +18,9 @@ {% block report_content -%}

- {% trans %}Report media{% endtrans %} diff --git a/mediagoblin/tests/test_notifications.py b/mediagoblin/tests/test_notifications.py index 0908cb34..3bf36f5f 100644 --- a/mediagoblin/tests/test_notifications.py +++ b/mediagoblin/tests/test_notifications.py @@ -157,7 +157,8 @@ otherperson@example.com\n\nSGkgb3RoZXJwZXJzb24sCmNocmlzIGNvbW1lbnRlZCBvbiB5b3VyI def test_mark_all_comment_notifications_seen(self): """ Test that mark_all_comments_seen works""" - user = fixture_add_user('otherperson', password='nosreprehto') + user = fixture_add_user('otherperson', password='nosreprehto', + privileges=[u'active']) media_entry = fixture_media_entry(uploader=user.id, state=u'processed') diff --git a/mediagoblin/tests/test_openid.py b/mediagoblin/tests/test_openid.py index 23a2290e..3aea7982 100644 --- a/mediagoblin/tests/test_openid.py +++ b/mediagoblin/tests/test_openid.py @@ -237,7 +237,7 @@ class TestOpenIDPlugin(object): def test_add_delete(self, openid_plugin_app): """Test adding and deleting openids""" # Add user - test_user = fixture_add_user(password='') + test_user = fixture_add_user(password='', privileges=[u'active']) openid = OpenIDUserURL() openid.openid_url = 'http://real.myopenid.com' openid.user_id = test_user.id diff --git a/mediagoblin/tests/test_persona.py b/mediagoblin/tests/test_persona.py index 3e9bf22f..a696858d 100644 --- a/mediagoblin/tests/test_persona.py +++ b/mediagoblin/tests/test_persona.py @@ -22,6 +22,7 @@ pytest.importorskip("requests") from mediagoblin import mg_globals from mediagoblin.db.base import Session +from mediagoblin.db.models import Privilege from mediagoblin.tests.tools import get_app from mediagoblin.tools import template @@ -112,6 +113,9 @@ class TestPersonaPlugin(object): # Get user and detach from session test_user = mg_globals.database.User.query.filter_by( username=u'chris').first() + active_privilege = Privilege.query.filter( + Privilege.privilege_name==u'active').first() + test_user.all_privileges.append(active_privilege) test_user.save() test_user = mg_globals.database.User.query.filter_by( username=u'chris').first() diff --git a/mediagoblin/tests/test_reporting.py b/mediagoblin/tests/test_reporting.py index b414a580..a154a061 100644 --- a/mediagoblin/tests/test_reporting.py +++ b/mediagoblin/tests/test_reporting.py @@ -160,7 +160,8 @@ class TestReportFiling: assert archived_report.reported_user_id == allie_id assert archived_report.created is not None assert archived_report.resolved is not None - assert archived_report.result == u'This is a test of archiving reports\ -.
natalie banned user allie indefinitely.
natalie deleted the comment.' + assert archived_report.result == u'''This is a test of archiving reports. +natalie banned user allie indefinitely. +natalie deleted the comment.''' assert archived_report.discriminator == 'comment_report' diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 4f555884..e895e634 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -37,7 +37,7 @@ from mediagoblin.decorators import (uses_pagination, get_user_media_entry, get_media_entry_by_id, user_has_privilege, user_not_banned, require_active_login, user_may_delete_media, user_may_alter_collection, get_user_collection, get_user_collection_item, active_user_from_url, - get_optional_media_comment_by_id) + get_optional_media_comment_by_id, allow_reporting) from werkzeug.contrib.atom import AtomFeed from werkzeug.exceptions import MethodNotAllowed @@ -643,6 +643,7 @@ def processing_panel(request): 'failed_entries': failed_entries, 'processed_entries': processed_entries}) +@allow_reporting @get_user_media_entry @user_has_privilege(u'reporter') @get_optional_media_comment_by_id @@ -682,4 +683,3 @@ def file_a_report(request, media, comment): request, 'mediagoblin/user_pages/report.html', context) - -- 2.25.1

{% trans %}ID{% endtrans %}