This commit had some important milestones in it. The major update is that now I
have mostly completed the moderator punishment and resolution of reports. Along with this, I have also added one last table to the database: one that holds ar- -chived (or resolved) reports. This is some of the primary functionality of my whole update, so this is a big step! The other changes I made this update are primarily organizational. I refactored some of my code into functions and I cl- eaned up many of my templates. --\ mediagoblin/db/models.py --| Created the new ArchivedReport table --| Removed columns from BaseReport table that are only necessary for Archived | reports --\ mediagoblin/db/migrations.py --| Created the new ArchivedReport table --| Removed columns from BaseReport table that are only necessary for Archived | reports --\ mediagoblin/db/util.py --| Created the user_privileges_to_dictionary function. This is useful for | accessing a user's permissions from within a template. --\ mediagoblin/moderation/forms.py --| Expanded the disciplinary actions a moderator can take --| Allowed the moderator to choose more than one disciplinary action at a time | (It's now managed with a list of checkboxes rather than radio buttons) ----| Pulled a MultiCheckBox class from a wtforms tutorial --| Added various other form inputs for details of the moderator's disciplinary | actions --| Tried to ensure that every string is unicode and translated --\ mediagoblin/moderation/tools.py --| Created this file for holding useful moderation tools --| Moved the penalizing code from views to the function take_punitive_actions --| Added many more types of punitive actions --| Added the archiving of old reports --\ mediagoblin/moderation/views.py --| Used the privileges_to_dictionary function for the Users Detail view to | allow for different actions available to a moderator and an admin. --| Added in functionality for ArchivedReports to the reports_detail and | reports_panel views --| Moved the punishments of repots_detail to tools.py (as mentioned above) --\ mediagoblin/static/css/base.css --| Added new styling for the User Detail page --\ mediagoblin/static/images/icon_clipboard_alert.png --| Added this image to represent unresolved reports --\ mediagoblin/templates/mediagoblin/moderation/report.html --| Added 'Return to Reports Panel' button --| Fixed the spacing to be less that 80 columns wide --| Added in display for Archived Reports --\ mediagoblin/templates/mediagoblin/moderation/reports_panel.html --| Changed the placement and columns of the tables --| Fixed the spacing to be less that 80 columns wide --| Added in display for Archived Reports --\ mediagoblin/templates/mediagoblin/moderation/user.html --| Fixed the spacing to be less that 80 columns wide --| Took away the moderator's ability to add and remove privileges at will. | Only the admin has this power now. --\ mediagoblin/templates/mediagoblin/moderation/users_panel.html --| Fixed the spacing to be less that 80 columns wide --\ mediagoblin/tools/response.py --| Added in code to remove a UserBan from a User if that user logs in after | the expiration date
This commit is contained in:
parent
6bba33d7e6
commit
3aa3871b90
@ -299,8 +299,6 @@ class ReportBase_v0(declarative_base()):
|
|||||||
report_content = Column(UnicodeText)
|
report_content = Column(UnicodeText)
|
||||||
reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False)
|
reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False)
|
||||||
created = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
created = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||||
resolved = Column(DateTime)
|
|
||||||
result = Column(UnicodeText)
|
|
||||||
discriminator = Column('type', Unicode(50))
|
discriminator = Column('type', Unicode(50))
|
||||||
__mapper_args__ = {'polymorphic_on': discriminator}
|
__mapper_args__ = {'polymorphic_on': discriminator}
|
||||||
|
|
||||||
@ -317,13 +315,20 @@ class MediaReport_v0(ReportBase_v0):
|
|||||||
__tablename__ = 'core__reports_on_media'
|
__tablename__ = 'core__reports_on_media'
|
||||||
__mapper_args__ = {'polymorphic_identity': 'media_report'}
|
__mapper_args__ = {'polymorphic_identity': 'media_report'}
|
||||||
|
|
||||||
id = Column(
|
id = Column('id',Integer, ForeignKey('core__reports.id'), primary_key=True)
|
||||||
'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=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()):
|
class UserBan_v0(declarative_base()):
|
||||||
__tablename__ = 'core__user_bans'
|
__tablename__ = 'core__user_bans'
|
||||||
@ -356,6 +361,7 @@ def create_moderation_tables(db):
|
|||||||
ReportBase_v0.__table__.create(db.bind)
|
ReportBase_v0.__table__.create(db.bind)
|
||||||
CommentReport_v0.__table__.create(db.bind)
|
CommentReport_v0.__table__.create(db.bind)
|
||||||
MediaReport_v0.__table__.create(db.bind)
|
MediaReport_v0.__table__.create(db.bind)
|
||||||
|
ArchivedReport_v0.__table__.create(db.bind)
|
||||||
UserBan_v0.__table__.create(db.bind)
|
UserBan_v0.__table__.create(db.bind)
|
||||||
Privilege_v0.__table__.create(db.bind)
|
Privilege_v0.__table__.create(db.bind)
|
||||||
PrivilegeUserAssociation_v0.__table__.create(db.bind)
|
PrivilegeUserAssociation_v0.__table__.create(db.bind)
|
||||||
|
@ -515,11 +515,18 @@ class ReportBase(Base):
|
|||||||
cascade="all, delete-orphan"),
|
cascade="all, delete-orphan"),
|
||||||
primaryjoin="User.id==ReportBase.reported_user_id")
|
primaryjoin="User.id==ReportBase.reported_user_id")
|
||||||
created = Column(DateTime, nullable=False, default=datetime.datetime.now())
|
created = Column(DateTime, nullable=False, default=datetime.datetime.now())
|
||||||
resolved = Column(DateTime)
|
|
||||||
result = Column(UnicodeText)
|
|
||||||
discriminator = Column('type', Unicode(50))
|
discriminator = Column('type', Unicode(50))
|
||||||
__mapper_args__ = {'polymorphic_on': discriminator}
|
__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):
|
class CommentReport(ReportBase):
|
||||||
"""
|
"""
|
||||||
@ -548,10 +555,40 @@ class MediaReport(ReportBase):
|
|||||||
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
|
media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
|
||||||
media_entry = relationship(
|
media_entry = relationship(
|
||||||
MediaEntry,
|
MediaEntry,
|
||||||
backref=backref("reports_filed_on",
|
backref=backref("reports_filed_onmod/reports/1/",
|
||||||
lazy="dynamic",
|
lazy="dynamic",
|
||||||
cascade="all, delete-orphan"))
|
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):
|
class UserBan(Base):
|
||||||
"""
|
"""
|
||||||
Holds the information on a specific user's ban-state. As long as one of
|
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 = [
|
MODELS = [
|
||||||
User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
|
User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
|
||||||
MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData, ReportBase,
|
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
|
# 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
|
# this dictionary should be in the format of
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from mediagoblin.db.base import Session
|
from mediagoblin.db.base import Session
|
||||||
from mediagoblin.db.models import MediaEntry, Tag, MediaTag, Collection
|
from mediagoblin.db.models import (MediaEntry, Tag, MediaTag, Collection, \
|
||||||
|
User, Privilege, FOUNDATIONS)
|
||||||
|
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
@ -67,6 +68,22 @@ def check_collection_slug_used(creator_id, slug, ignore_c_id):
|
|||||||
does_exist = Session.query(Collection.id).filter(filt).first() is not None
|
does_exist = Session.query(Collection.id).filter(filt).first() is not None
|
||||||
return does_exist
|
return does_exist
|
||||||
|
|
||||||
|
def user_privileges_to_dictionary(user_id):
|
||||||
|
"""
|
||||||
|
This function accepts a users id and returns a dictionary of True or False
|
||||||
|
values for each privilege the user does or does not have. This allows for
|
||||||
|
easier referencing of a user's privileges inside templates.
|
||||||
|
"""
|
||||||
|
privilege_dictionary = {}
|
||||||
|
user = User.query.get(user_id)
|
||||||
|
users_privileges = [p_item.privilege_name for p_item in user.all_privileges]
|
||||||
|
for privilege_name in FOUNDATIONS[Privilege]:
|
||||||
|
privilege_name = privilege_name[0]
|
||||||
|
if privilege_name in users_privileges:
|
||||||
|
privilege_dictionary[privilege_name]=True
|
||||||
|
else:
|
||||||
|
privilege_dictionary[privilege_name]=False
|
||||||
|
return privilege_dictionary
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from mediagoblin.db.open import setup_connection_and_db_from_config
|
from mediagoblin.db.open import setup_connection_and_db_from_config
|
||||||
|
@ -17,24 +17,44 @@
|
|||||||
import wtforms
|
import wtforms
|
||||||
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
|
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
|
||||||
|
|
||||||
ACTION_CHOICES = [(_(u'takeaway'),_('Take away privilege')),
|
ACTION_CHOICES = [(_(u'takeaway'),_(u'Take away privilege')),
|
||||||
(_(u'userban'),_('Ban the user')),
|
(_(u'userban'),_(u'Ban the user')),
|
||||||
(_(u'closereport'),_('Close the report without taking an action'))]
|
(_(u'sendmessage'),(u'Send the user a message')),
|
||||||
|
(_(u'delete'),_(u'Delete the content'))]
|
||||||
|
|
||||||
|
class MultiCheckboxField(wtforms.SelectMultipleField):
|
||||||
|
"""
|
||||||
|
A multiple-select, except displays a list of checkboxes.
|
||||||
|
|
||||||
|
Iterating the field will produce subfields, allowing custom rendering of
|
||||||
|
the enclosed checkbox fields.
|
||||||
|
|
||||||
|
code from http://wtforms.simplecodes.com/docs/1.0.4/specific_problems.html
|
||||||
|
"""
|
||||||
|
widget = wtforms.widgets.ListWidget(prefix_label=False)
|
||||||
|
option_widget = wtforms.widgets.CheckboxInput()
|
||||||
|
|
||||||
|
|
||||||
class PrivilegeAddRemoveForm(wtforms.Form):
|
class PrivilegeAddRemoveForm(wtforms.Form):
|
||||||
giving_privilege = wtforms.HiddenField('',[wtforms.validators.required()])
|
|
||||||
privilege_name = wtforms.HiddenField('',[wtforms.validators.required()])
|
privilege_name = wtforms.HiddenField('',[wtforms.validators.required()])
|
||||||
|
|
||||||
class ReportResolutionForm(wtforms.Form):
|
class ReportResolutionForm(wtforms.Form):
|
||||||
action_to_resolve = wtforms.RadioField(
|
action_to_resolve = MultiCheckboxField(
|
||||||
_('What action will you take to resolve this report'),
|
_(u'What action will you take to resolve the report?'),
|
||||||
validators=[wtforms.validators.required()],
|
validators=[wtforms.validators.optional()],
|
||||||
choices=ACTION_CHOICES)
|
choices=ACTION_CHOICES)
|
||||||
targeted_user = wtforms.HiddenField('',
|
targeted_user = wtforms.HiddenField('',
|
||||||
validators=[wtforms.validators.required()])
|
validators=[wtforms.validators.required()])
|
||||||
|
take_away_privileges = wtforms.SelectMultipleField(
|
||||||
|
_(u'What privileges will you take away?'),
|
||||||
|
validators=[wtforms.validators.optional()])
|
||||||
user_banned_until = wtforms.DateField(
|
user_banned_until = wtforms.DateField(
|
||||||
_('User will be banned until:'),
|
_(u'User will be banned until:'),
|
||||||
format='%Y-%m-%d',
|
format='%Y-%m-%d',
|
||||||
validators=[wtforms.validators.optional()])
|
validators=[wtforms.validators.optional()])
|
||||||
|
why_user_was_banned = wtforms.TextAreaField(
|
||||||
|
validators=[wtforms.validators.optional()])
|
||||||
|
message_to_user = wtforms.TextAreaField(
|
||||||
|
validators=[wtforms.validators.optional()])
|
||||||
resolution_content = wtforms.TextAreaField()
|
resolution_content = wtforms.TextAreaField()
|
||||||
|
|
||||||
|
134
mediagoblin/moderation/tools.py
Normal file
134
mediagoblin/moderation/tools.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
from mediagoblin import mg_globals
|
||||||
|
from mediagoblin.db.models import User, Privilege, ArchivedReport, UserBan
|
||||||
|
from mediagoblin.db.base import Session
|
||||||
|
from mediagoblin.tools.mail import send_email
|
||||||
|
from mediagoblin.tools.response import redirect
|
||||||
|
from datetime import datetime
|
||||||
|
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
|
||||||
|
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:
|
||||||
|
privilege = Privilege.one({u'privilege_name':privilege_name})
|
||||||
|
form.resolution_content.data += \
|
||||||
|
u"<br>%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 + \
|
||||||
|
"<br>"+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"<br>%s banned user %s until %s." % (
|
||||||
|
request.user.username,
|
||||||
|
user.username,
|
||||||
|
form.user_banned_until.data)
|
||||||
|
else:
|
||||||
|
form.resolution_content.data += \
|
||||||
|
u"<br>%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"<br>%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"<br>%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"<br>%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)
|
@ -18,11 +18,13 @@ from werkzeug.exceptions import Forbidden
|
|||||||
|
|
||||||
from mediagoblin.db.models import (MediaEntry, User, MediaComment, \
|
from mediagoblin.db.models import (MediaEntry, User, MediaComment, \
|
||||||
CommentReport, ReportBase, Privilege, \
|
CommentReport, ReportBase, Privilege, \
|
||||||
UserBan)
|
UserBan, ArchivedReport)
|
||||||
|
from mediagoblin.db.util import user_privileges_to_dictionary
|
||||||
from mediagoblin.decorators import (require_admin_or_moderator_login, \
|
from mediagoblin.decorators import (require_admin_or_moderator_login, \
|
||||||
active_user_from_url)
|
active_user_from_url)
|
||||||
from mediagoblin.tools.response import render_to_response, redirect
|
from mediagoblin.tools.response import render_to_response, redirect
|
||||||
from mediagoblin.moderation import forms as moderation_forms
|
from mediagoblin.moderation import forms as moderation_forms
|
||||||
|
from mediagoblin.moderation.tools import take_punitive_actions
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@require_admin_or_moderator_login
|
@require_admin_or_moderator_login
|
||||||
@ -67,17 +69,22 @@ def moderation_users_detail(request):
|
|||||||
'''
|
'''
|
||||||
user = User.query.filter_by(username=request.matchdict['user']).first()
|
user = User.query.filter_by(username=request.matchdict['user']).first()
|
||||||
active_reports = user.reports_filed_on.filter(
|
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(
|
closed_reports = user.reports_filed_on.filter(
|
||||||
ReportBase.resolved!=None).all()
|
ReportBase.discriminator=='archived_report').all()
|
||||||
privileges = Privilege.query
|
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(
|
return render_to_response(
|
||||||
request,
|
request,
|
||||||
'mediagoblin/moderation/user.html',
|
'mediagoblin/moderation/user.html',
|
||||||
{'user':user,
|
{'user':user,
|
||||||
'privileges':privileges,
|
'privileges': privileges,
|
||||||
'reports':active_reports})
|
'requesting_user_privileges':requesting_user_privileges,
|
||||||
|
'reports':active_reports,
|
||||||
|
'user_banned':user_banned})
|
||||||
|
|
||||||
@require_admin_or_moderator_login
|
@require_admin_or_moderator_login
|
||||||
def moderation_reports_panel(request):
|
def moderation_reports_panel(request):
|
||||||
@ -86,10 +93,10 @@ def moderation_reports_panel(request):
|
|||||||
media entries for this instance.
|
media entries for this instance.
|
||||||
'''
|
'''
|
||||||
report_list = ReportBase.query.filter(
|
report_list = ReportBase.query.filter(
|
||||||
ReportBase.resolved==None).order_by(
|
ReportBase.discriminator!="archived_report").order_by(
|
||||||
ReportBase.created.desc()).limit(10)
|
ReportBase.created.desc()).limit(10)
|
||||||
closed_report_list = ReportBase.query.filter(
|
closed_report_list = ReportBase.query.filter(
|
||||||
ReportBase.resolved!=None).order_by(
|
ReportBase.discriminator=="archived_report").order_by(
|
||||||
ReportBase.created.desc()).limit(10)
|
ReportBase.created.desc()).limit(10)
|
||||||
|
|
||||||
# Render to response
|
# Render to response
|
||||||
@ -109,66 +116,12 @@ def moderation_reports_detail(request):
|
|||||||
form = moderation_forms.ReportResolutionForm(request.form)
|
form = moderation_forms.ReportResolutionForm(request.form)
|
||||||
report = ReportBase.query.get(request.matchdict['report_id'])
|
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():
|
if request.method == "POST" and form.validate():
|
||||||
user = User.query.get(form.targeted_user.data)
|
user = User.query.get(form.targeted_user.data)
|
||||||
if form.action_to_resolve.data == u'takeaway':
|
return take_punitive_actions(request, form, report, user)
|
||||||
if report.discriminator == u'comment_report':
|
|
||||||
privilege = Privilege.one({'privilege_name':u'commenter'})
|
|
||||||
form.resolution_content.data += \
|
|
||||||
u"<br>%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"<br>%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 + \
|
|
||||||
"<br>"+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"<br>%s banned user %s until %s." % (
|
|
||||||
request.user.username,
|
|
||||||
user.username,
|
|
||||||
form.user_banned_until.data)
|
|
||||||
else:
|
|
||||||
form.resolution_content.data += \
|
|
||||||
u"<br>%s banned user %s indefinitely." % (
|
|
||||||
request.user.username,
|
|
||||||
user.username,
|
|
||||||
form.user_banned_until.data)
|
|
||||||
|
|
||||||
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
|
form.targeted_user.data = report.reported_user_id
|
||||||
|
|
||||||
@ -176,8 +129,6 @@ def moderation_reports_detail(request):
|
|||||||
request,
|
request,
|
||||||
'mediagoblin/moderation/report.html',
|
'mediagoblin/moderation/report.html',
|
||||||
{'report':report,
|
{'report':report,
|
||||||
'media_entry':media_entry,
|
|
||||||
'comment':comment,
|
|
||||||
'form':form})
|
'form':form})
|
||||||
|
|
||||||
@require_admin_or_moderator_login
|
@require_admin_or_moderator_login
|
||||||
@ -189,7 +140,7 @@ def give_or_take_away_privilege(request, url_user):
|
|||||||
form = moderation_forms.PrivilegeAddRemoveForm(request.form)
|
form = moderation_forms.PrivilegeAddRemoveForm(request.form)
|
||||||
if request.method == "POST" and form.validate():
|
if request.method == "POST" and form.validate():
|
||||||
privilege = Privilege.one({'privilege_name':form.privilege_name.data})
|
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)
|
url_user.all_privileges.remove(privilege)
|
||||||
else:
|
else:
|
||||||
url_user.all_privileges.append(privilege)
|
url_user.all_privileges.append(privilege)
|
||||||
|
@ -618,6 +618,23 @@ table.admin_panel th, table.admin_side_panel th {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
text-align: left;
|
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 */
|
/* Delete panel */
|
||||||
|
BIN
mediagoblin/static/images/icon_clipboard_alert.png
Normal file
BIN
mediagoblin/static/images/icon_clipboard_alert.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 647 B |
@ -22,9 +22,16 @@
|
|||||||
{% if not report %}
|
{% if not report %}
|
||||||
Sorry, no such report found.
|
Sorry, no such report found.
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2> Report #{{ report.id }}</h2>
|
<a href="{{ request.urlgen('mediagoblin.moderation.reports') }}"
|
||||||
{% if comment %}
|
class="return_to_panel button_action"
|
||||||
Reported comment:
|
title="Return to Reports Panel">
|
||||||
|
{% trans %}Return to Reports Panel{% endtrans %}</a>
|
||||||
|
<h2>{% trans %}Report{% endtrans %} #{{ report.id }}</h2>
|
||||||
|
{% if report.is_comment_report() or
|
||||||
|
(report.is_archived_report() and report.comment) %}
|
||||||
|
|
||||||
|
{% trans %}Reported comment{% endtrans %}:
|
||||||
|
{% set comment = report.comment %}
|
||||||
{% set reported_user = comment.get_author %}
|
{% set reported_user = comment.get_author %}
|
||||||
<div id="comment-{{ comment.id }}"
|
<div id="comment-{{ comment.id }}"
|
||||||
class="comment_wrapper">
|
class="comment_wrapper">
|
||||||
@ -35,7 +42,8 @@
|
|||||||
class="comment_authorlink">
|
class="comment_authorlink">
|
||||||
{{- reported_user.username -}}
|
{{- reported_user.username -}}
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment',
|
<a href="{{ request.urlgen(
|
||||||
|
'mediagoblin.user_pages.media_home.view_comment',
|
||||||
comment=comment.id,
|
comment=comment.id,
|
||||||
user=comment.get_media_entry.get_uploader.username,
|
user=comment.get_media_entry.get_uploader.username,
|
||||||
media=comment.get_media_entry.slug_or_id) }}#comment"
|
media=comment.get_media_entry.slug_or_id) }}#comment"
|
||||||
@ -52,23 +60,43 @@
|
|||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% elif media_entry %}
|
{% elif report.is_media_entry_report() or
|
||||||
|
(report.is_archived_report() and report.media_entry) %}
|
||||||
|
|
||||||
|
{% set media_entry = report.media_entry %}
|
||||||
<div class="media_thumbnail">
|
<div class="media_thumbnail">
|
||||||
<a href="request.urlgen('mediagoblin.user_pages.media_home'),
|
<a href="{{ request.urlgen('mediagoblin.user_pages.media_home',
|
||||||
user=media_entry.get_uploader.username,
|
user=media_entry.get_uploader.username,
|
||||||
media=media_entry.slug_or_id)"><img src="{{ media_entry.thumb_url}}"/></a>
|
media=media_entry.slug_or_id) }}">
|
||||||
<a href="request.urlgen('mediagoblin.user_pages.media_home'),
|
<img src="{{ media_entry.thumb_url}}"/></a>
|
||||||
|
<a href="{{ request.urlgen('mediagoblin.user_pages.media_home',
|
||||||
user=media_entry.get_uploader.username,
|
user=media_entry.get_uploader.username,
|
||||||
media=media_entry.slug_or_id)" class=thumb_entry_title>{{ media_entry.title }}</a>
|
media=media_entry.slug_or_id) }}" class=thumb_entry_title>
|
||||||
|
{{ media_entry.title }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class=clear></div>
|
<div class=clear></div>
|
||||||
|
<p>❖ Reported media by <a href="">
|
||||||
|
{{ report.reported_user.username }}</a></p>
|
||||||
|
<div class=clear></div>
|
||||||
|
{% else %}
|
||||||
|
<h2>{% trans user_url="request.urlgen(
|
||||||
|
'mediagoblin.moderation.users_detail',
|
||||||
|
user=report.reporter.username)",
|
||||||
|
user_name=report.reported_user.username %}
|
||||||
|
CONTENT BY
|
||||||
|
<a href="{{ user_url }}">
|
||||||
|
{{ user_name }}</a>
|
||||||
|
HAS BEEN DELETED{% endtrans %}
|
||||||
|
</h2>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
Reason for report:
|
Reason for report:
|
||||||
<div id="report-{{ report.id }}"
|
<div id="report-{{ report.id }}"
|
||||||
class="report_wrapper">
|
class="report_wrapper">
|
||||||
<div class="report_author">
|
<div class="report_author">
|
||||||
<img src="{{ request.staticdirect('/images/icon_clipboard.png') }}"
|
<img src="{{ request.staticdirect(
|
||||||
alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license. Distributed by the GNOME project http://www.gnome.org" />
|
'/images/icon_clipboard_alert.png') }}"
|
||||||
|
alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license.
|
||||||
|
Distributed by the GNOME project http://www.gnome.org" />
|
||||||
<a href="{{ request.urlgen('mediagoblin.moderation.users_detail',
|
<a href="{{ request.urlgen('mediagoblin.moderation.users_detail',
|
||||||
user=report.reporter.username) }}"
|
user=report.reporter.username) }}"
|
||||||
class="report_authorlink">
|
class="report_authorlink">
|
||||||
@ -88,7 +116,7 @@
|
|||||||
{{ report.report_content }}
|
{{ report.report_content }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if not report.resolved %}
|
{% if not report.is_archived_report() %}
|
||||||
<input type=button value=Resolve id=open_resolution_form />
|
<input type=button value=Resolve id=open_resolution_form />
|
||||||
<form action="" method="POST" id=resolution_form>
|
<form action="" method="POST" id=resolution_form>
|
||||||
{{ wtforms_util.render_divs(form) }}
|
{{ wtforms_util.render_divs(form) }}
|
||||||
@ -98,39 +126,72 @@
|
|||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('form#resolution_form').hide()
|
hidden_input_names = {
|
||||||
$('#user_banned_until').val("YYYY-MM-DD")
|
'takeaway':['take_away_privileges'],
|
||||||
$('#open_resolution_form').click(function() {
|
'userban':['user_banned_until','why_user_was_banned'],
|
||||||
$('form#resolution_form').toggle();
|
'sendmessage':['message_to_user']
|
||||||
$('#user_banned_until').hide();
|
}
|
||||||
$('label[for=user_banned_until]').hide();
|
|
||||||
});
|
$('form#resolution_form').hide()
|
||||||
$('#action_to_resolve').change(function() {
|
$('#user_banned_until').val("YYYY-MM-DD")
|
||||||
if ($('ul#action_to_resolve li input:checked').val() == "userban") {
|
$('#open_resolution_form').click(function() {
|
||||||
$('#user_banned_until').show();
|
$('form#resolution_form').toggle();
|
||||||
$('label[for=user_banned_until]').show();
|
$.each(hidden_input_names, function(key, list){
|
||||||
} else {
|
$.each(list, function(index, name){
|
||||||
$('#user_banned_until').hide();
|
$('label[for='+name+']').hide();
|
||||||
$('label[for=user_banned_until]').hide();
|
$('#'+name).hide();
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
$("#user_banned_until").focus(function() {
|
});
|
||||||
$(this).val("");
|
$('#action_to_resolve').change(function() {
|
||||||
$(this).unbind('focus');
|
$('ul#action_to_resolve li input:checked').each(function() {
|
||||||
});
|
$.each(hidden_input_names[$(this).val()], function(index, name){
|
||||||
$("#submit_this_report").click(function(){
|
$('label[for='+name+']').show();
|
||||||
if ($("#user_banned_until").val() == 'YYYY-MM-DD'){
|
$('#'+name).show();
|
||||||
$("#user_banned_until").val("");
|
});
|
||||||
}
|
});
|
||||||
});
|
$('ul#action_to_resolve li input:not(:checked)').each(function() {
|
||||||
|
$.each(hidden_input_names[$(this).val()], function(index, name){
|
||||||
|
$('label[for='+name+']').hide();
|
||||||
|
$('#'+name).hide();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
/* $.each(hidden_input_names, function(key,name){
|
||||||
|
if ($.inArray(key, $('ul#action_to_resolve li input:checked').val())){
|
||||||
|
$.each(hidden_input_names[key], function(index,name){
|
||||||
|
$('#'+name).show();
|
||||||
|
$('label[for='+name+']').show();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$.each(hidden_input_names[key], function(index,name){
|
||||||
|
$('#'+name).hide();
|
||||||
|
$('label[for='+name+']').hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
});
|
||||||
|
$("#user_banned_until").focus(function() {
|
||||||
|
$(this).val("");
|
||||||
|
$(this).unbind('focus');
|
||||||
|
});
|
||||||
|
$("#submit_this_report").click(function(){
|
||||||
|
if ($("#user_banned_until").val() == 'YYYY-MM-DD'){
|
||||||
|
$("#user_banned_until").val("");
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2>Status:</h2>
|
<h2><img src="{{ request.staticdirect('/images/icon_clipboard.png') }}"
|
||||||
RESOLVED on {{ report.resolved.strftime("%I:%M%p %Y-%m-%d") }}
|
alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license.
|
||||||
|
Distributed by the GNOME project http://www.gnome.org" />
|
||||||
|
{% trans %}Status{% endtrans %}:
|
||||||
|
</h2>
|
||||||
|
<b>{% trans %}RESOLVED{% endtrans %}</b>
|
||||||
|
{{ report.resolved.strftime("%I:%M%p %Y-%m-%d") }}
|
||||||
{% autoescape False %}
|
{% autoescape False %}
|
||||||
<p>{{ report.result }}</p>
|
<p>{{ report.result }}</p>
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -26,42 +26,57 @@
|
|||||||
<h1>{% trans %}Report panel{% endtrans %}</h1>
|
<h1>{% trans %}Report panel{% endtrans %}</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
|
{% trans %}
|
||||||
|
Here you can look up open reports that have been filed by users.
|
||||||
|
{% endtrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>{% trans %}Reports Filed{% endtrans %}</h2>
|
<h2>{% trans %}Active Reports Filed{% endtrans %}</h2>
|
||||||
|
|
||||||
{% if report_list.count() %}
|
{% if report_list.count() %}
|
||||||
<table class="admin_panel processing">
|
<table class="admin_panel processing">
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th></th>
|
||||||
<th>Report Type</th>
|
<th>{% trans %}Offender{% endtrans %}</th>
|
||||||
<th>Offender</th>
|
<th>{% trans %}When Reported{% endtrans %}</th>
|
||||||
<th>When Reported</th>
|
<th>{% trans %}Reported By{% endtrans %}</th>
|
||||||
<th>Reported By</th>
|
<th>{% trans %}Reason{% endtrans %}</th>
|
||||||
<th>Reason</th>
|
|
||||||
<th>Reported Comment or Media Entry</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for report in report_list %}
|
{% for report in report_list %}
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
<td><a href="{{ request.urlgen('mediagoblin.moderation.reports_detail',
|
|
||||||
report_id=report.id) }}">{{ report.id }}</a></td>
|
|
||||||
{% if report.discriminator == "comment_report" %}
|
{% if report.discriminator == "comment_report" %}
|
||||||
<td>Comment Report</td>
|
<td>
|
||||||
<td>{{ report.comment.get_author.username }}</td>
|
<img
|
||||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
src="{{ request.staticdirect('/images/icon_clipboard_alert.png') }}"
|
||||||
<td>{{ report.reporter.username }}</td>
|
alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license.
|
||||||
<td>{{ report.report_content }}</td>
|
Distributed by the GNOME project http://www.gnome.org" />
|
||||||
<td><a href="{{ report.comment.get_media_entry.url_for_self(request.urlgen) }}">{{ report.comment.get_media_entry.title }}</a></td>
|
<a href="{{ request.urlgen(
|
||||||
|
'mediagoblin.moderation.reports_detail',
|
||||||
|
report_id=report.id) }}">
|
||||||
|
{% trans report_id=report.id %}
|
||||||
|
Comment Report #{{ report_id }}
|
||||||
|
{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
{% elif report.discriminator == "media_report" %}
|
{% elif report.discriminator == "media_report" %}
|
||||||
<td>Media Report</td>
|
<td>
|
||||||
<td>{{ report.media_entry.get_uploader.username }}</td>
|
<img
|
||||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
src="{{ request.staticdirect('/images/icon_clipboard_alert.png') }}"
|
||||||
<td>{{ report.reporter.username }}</td>
|
alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license.
|
||||||
<td>{{ report.report_content[0:20] }}...</td>
|
Distributed by the GNOME project http://www.gnome.org" />
|
||||||
<td><a href="{{ report.media_entry.url_for_self(request.urlgen) }}">{{ report.media_entry.title }}</a></td>
|
<a href="{{ request.urlgen(
|
||||||
|
'mediagoblin.moderation.reports_detail',
|
||||||
|
report_id=report.id) }}">
|
||||||
|
{% trans report_id=report.id %}
|
||||||
|
Media Report #{{ report_id }}
|
||||||
|
{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<td>{{ report.reported_user.username }}</td>
|
||||||
|
<td>{{ report.created.strftime("%F %R") }}</td>
|
||||||
|
<td>{{ report.reporter.username }}</td>
|
||||||
|
<td>{{ report.report_content[0:20] }}...</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
@ -72,32 +87,33 @@
|
|||||||
{% if closed_report_list.count() %}
|
{% if closed_report_list.count() %}
|
||||||
<table class="media_panel processing">
|
<table class="media_panel processing">
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th></th>
|
||||||
<th>Resolved</th>
|
<th>{% trans %}Resolved{% endtrans %}</th>
|
||||||
<th>Offender</th>
|
<th>{% trans %}Offender{% endtrans %}</th>
|
||||||
<th>Action Taken</th>
|
<th>{% trans %}Action Taken{% endtrans %}</th>
|
||||||
<th>Reported By</th>
|
<th>{% trans %}Reported By{% endtrans %}</th>
|
||||||
<th>Reason</th>
|
<th>{% trans %}Reason{% endtrans %}</th>
|
||||||
<th>Reported Comment or Media Entry</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for report in closed_report_list %}
|
{% for report in closed_report_list %}
|
||||||
<td><a href="{{ request.urlgen('mediagoblin.moderation.reports_detail',
|
<tr>
|
||||||
report_id=report.id) }}">{{ report.id }}</a></td>
|
<td>
|
||||||
{% if report.discriminator == "comment_report" %}
|
<img
|
||||||
<td>{{ report.resolved.strftime("%F %R") }}</td>
|
src="{{ request.staticdirect('/images/icon_clipboard.png') }}"
|
||||||
<td>{{ report.comment.get_author.username }}</td>
|
alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license.
|
||||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
Distributed by the GNOME project http://www.gnome.org" />
|
||||||
<td>{{ report.reporter.username }}</td>
|
<a href="{{ request.urlgen('mediagoblin.moderation.reports_detail',
|
||||||
<td>{{ report.report_content }}</td>
|
report_id=report.id) }}">
|
||||||
<td><a href="{{ report.comment.get_media_entry.url_for_self(request.urlgen) }}">{{ report.comment.get_media_entry.title }}</a></td>
|
{% trans report_id=report.id %}
|
||||||
{% elif report.discriminator == "media_report" %}
|
Closed Report #{{ report_id }}
|
||||||
<td>{{ report.resolved.strftime("%F %R") }}</td>
|
{% endtrans %}
|
||||||
<td>{{ report.media_entry.get_uploader.username }}</td>
|
</a>
|
||||||
<td>{{ report.created.strftime("%F %R") }}</td>
|
</td>
|
||||||
<td>{{ report.reporter.username }}</td>
|
<td>{{ report.resolved.strftime("%F %R") }}</td>
|
||||||
<td>{{ report.report_content[0:20] }}...</td>
|
<td>{{ report.reported_user.username }}</td>
|
||||||
<td><a href="{{ report.media_entry.url_for_self(request.urlgen) }}">{{ report.media_entry.title }}</a></td>
|
<td>{{ report.created.strftime("%F %R") }}</td>
|
||||||
{% endif %}
|
<td>{{ report.reporter.username }}</td>
|
||||||
|
<td>{{ report.report_content }}</td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -41,13 +41,15 @@
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% trans -%}
|
{% trans -%}
|
||||||
Someone has registered an account with this username, but it still has to be activated.
|
Someone has registered an account with this username, but it still has
|
||||||
|
to be activated.
|
||||||
{%- endtrans %}
|
{%- endtrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% trans login_url=request.urlgen('mediagoblin.auth.login') -%}
|
{% trans login_url=request.urlgen('mediagoblin.auth.login') -%}
|
||||||
If you are that person but you've lost your verification email, you can <a href="{{ login_url }}">log in</a> and resend it.
|
If you are that person but you've lost your verification email, you can
|
||||||
|
<a href="{{ login_url }}">log in</a> and resend it.
|
||||||
{%- endtrans %}
|
{%- endtrans %}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -56,6 +58,11 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<h1>
|
<h1>
|
||||||
{%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
|
{%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
|
||||||
|
{% if user_banned and user_banned.expiration_date %}
|
||||||
|
— BANNED until {{ user_banned.expiration_date }}
|
||||||
|
{% elif user_banned %}
|
||||||
|
— Banned Indefinitely
|
||||||
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{% if not user.url and not user.bio %}
|
{% if not user.url and not user.bio %}
|
||||||
@ -121,35 +128,42 @@
|
|||||||
<a class="right_align">{{ user.username }}'s report history</a>
|
<a class="right_align">{{ user.username }}'s report history</a>
|
||||||
<span class=clear></span>
|
<span class=clear></span>
|
||||||
<h2>{{ user.username }}'s Privileges</h2>
|
<h2>{{ user.username }}'s Privileges</h2>
|
||||||
<table class="admin_panel">
|
<form action="{{ request.urlgen('mediagoblin.moderation.give_or_take_away_privilege',
|
||||||
|
user=user.username) }}"
|
||||||
|
method=post >
|
||||||
|
<table class="admin_side_panel">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Privilege{% endtrans %}</th>
|
<th>{% trans %}Privilege{% endtrans %}</th>
|
||||||
<th>{% trans %}User Has Privilege{% endtrans %}</th>
|
<th>{% trans %}User Has Privilege{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for privilege in privileges %}
|
{% for privilege in privileges %}
|
||||||
<tr>
|
<tr>
|
||||||
<form action="{{ request.urlgen('mediagoblin.moderation.give_or_take_away_privilege',
|
|
||||||
user=user.username) }}"
|
|
||||||
method=post >
|
|
||||||
<td>{{ privilege.privilege_name }}</td>
|
<td>{{ privilege.privilege_name }}</td>
|
||||||
<td>
|
{% if privilege in user.all_privileges %}
|
||||||
{% if privilege in user.all_privileges %}Yes</td>
|
<td class="user_with_privilege">
|
||||||
{% if (not privilege.is_admin_or_moderator() or request.user.is_admin) and not (user.is_admin and not request.user.is_admin) %}
|
Yes{% else %}
|
||||||
<td><input type=submit value="{% trans %}Take Away{% endtrans %}" />
|
<td class="user_without_privilege">
|
||||||
<input type=hidden name=giving_privilege />
|
No{% endif %}
|
||||||
{% endif %}
|
</td>
|
||||||
{% else %}No</td>
|
{% if requesting_user_privileges.admin%}
|
||||||
{% if (not privilege.is_admin_or_moderator() or request.user.is_admin) and not (user.is_admin and not request.user.is_admin) %}
|
<td>{% if privilege in user.all_privileges %}
|
||||||
<td><input type=submit value="{% trans %}Give Privilege{% endtrans %}" >
|
<input type=submit id="{{ privilege.privilege_name }}" class=submit_button value ="-" />{% else %}
|
||||||
<input type=hidden name=giving_privilege value=True />
|
<input type=submit id="{{ privilege.privilege_name }}" class=submit_button value ="+" />{% endif %}
|
||||||
{% endif %}
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input type=hidden name=privilege_name value="{{ privilege.privilege_name }}" />
|
|
||||||
</td>
|
</tr>
|
||||||
{{ csrf_token }}
|
|
||||||
</form>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
{{ csrf_token }}
|
||||||
|
<input type=hidden name=privilege_name id=hidden_privilege_name />
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('.submit_button').click(function(){
|
||||||
|
$('#hidden_privilege_name').val($(this).attr('id'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -26,7 +26,9 @@
|
|||||||
<h1>{% trans %}User panel{% endtrans %}</h1>
|
<h1>{% trans %}User panel{% endtrans %}</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
|
{% trans %}
|
||||||
|
Here you can look up users in order to take punitive actions on them.
|
||||||
|
{% endtrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>{% trans %}Active Users{% endtrans %}</h2>
|
<h2>{% trans %}Active Users{% endtrans %}</h2>
|
||||||
@ -42,8 +44,12 @@
|
|||||||
{% for user in user_list %}
|
{% for user in user_list %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ user.id }}</td>
|
<td>{{ user.id }}</td>
|
||||||
<td><a href="{{ request.urlgen('mediagoblin.moderation.users_detail',
|
<td>
|
||||||
user= user.username) }}">{{ user.username }}</a></td>
|
<a href="{{ request.urlgen('mediagoblin.moderation.users_detail',
|
||||||
|
user= user.username) }}">
|
||||||
|
{{ user.username }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td>{{ user.created.strftime("%F %R") }}</td>
|
<td>{{ user.created.strftime("%F %R") }}</td>
|
||||||
<td>{{ user.posted_comments.count() }}</td>
|
<td>{{ user.posted_comments.count() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -19,7 +19,8 @@ from werkzeug.wrappers import Response as wz_Response
|
|||||||
from mediagoblin.tools.template import render_template
|
from mediagoblin.tools.template import render_template
|
||||||
from mediagoblin.tools.translate import (lazy_pass_to_ugettext as _,
|
from mediagoblin.tools.translate import (lazy_pass_to_ugettext as _,
|
||||||
pass_to_ugettext)
|
pass_to_ugettext)
|
||||||
from mediagoblin.db.models import UserBan
|
from mediagoblin.db.models import UserBan, User
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
class Response(wz_Response):
|
class Response(wz_Response):
|
||||||
"""Set default response mimetype to HTML, otherwise we get text/plain"""
|
"""Set default response mimetype to HTML, otherwise we get text/plain"""
|
||||||
@ -68,6 +69,10 @@ def render_user_banned(request):
|
|||||||
and the reason why they have been banned"
|
and the reason why they have been banned"
|
||||||
"""
|
"""
|
||||||
user_ban = UserBan.query.get(request.user.id)
|
user_ban = UserBan.query.get(request.user.id)
|
||||||
|
if datetime.now()>user_ban.expiration_date:
|
||||||
|
user_ban.delete()
|
||||||
|
redirect(request,
|
||||||
|
'mediagoblin.index')
|
||||||
return render_to_response(request,
|
return render_to_response(request,
|
||||||
'mediagoblin/banned.html',
|
'mediagoblin/banned.html',
|
||||||
{'reason':user_ban.reason,
|
{'reason':user_ban.reason,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user