',
+ 'mediagoblin.admin.views:admin_reports_detail')]
diff --git a/mediagoblin/admin/views.py b/mediagoblin/admin/views.py
index 7a4dfbd4..97970577 100644
--- a/mediagoblin/admin/views.py
+++ b/mediagoblin/admin/views.py
@@ -16,12 +16,13 @@
from werkzeug.exceptions import Forbidden
-from mediagoblin.db.models import MediaEntry, User, MediaComment, CommentReport, ReportBase
+from mediagoblin.db.models import (MediaEntry, User, MediaComment, \
+ CommentReport, ReportBase, Privilege)
from mediagoblin.decorators import require_admin_login
from mediagoblin.tools.response import render_to_response
@require_admin_login
-def admin_processing_panel(request):
+def admin_media_processing_panel(request):
'''
Show the global media processing panel for this instance
'''
@@ -38,7 +39,7 @@ def admin_processing_panel(request):
# Render to response
return render_to_response(
request,
- 'mediagoblin/admin/panel.html',
+ 'mediagoblin/admin/media_panel.html',
{'processing_entries': processing_entries,
'failed_entries': failed_entries,
'processed_entries': processed_entries})
@@ -50,11 +51,29 @@ def admin_users_panel(request):
'''
user_list = User.query
- # Render to response
+ return render_to_response(
+ request,
+ 'mediagoblin/admin/user_panel.html',
+ {'user_list': user_list})
+
+@require_admin_login
+def admin_users_detail(request):
+ '''
+ Shows details about a particular user.
+ '''
+ user = User.query.filter_by(username=request.matchdict['user']).first()
+ privileges = Privilege.query
+ active_reports = user.reports_filed_on.filter(
+ ReportBase.resolved==None).limit(5)
+ closed_reports = user.reports_filed_on.filter(
+ ReportBase.resolved!=None).all()
+
return render_to_response(
request,
'mediagoblin/admin/user.html',
- {'user_list': user_list})
+ {'user':user,
+ 'privileges':privileges,
+ 'reports':active_reports})
@require_admin_login
def admin_reports_panel(request):
@@ -72,7 +91,25 @@ def admin_reports_panel(request):
# Render to response
return render_to_response(
request,
- 'mediagoblin/admin/report.html',
+ 'mediagoblin/admin/report_panel.html',
{'report_list':report_list,
'closed_report_list':closed_report_list})
+@require_admin_login
+def admin_reports_detail(request):
+ report = ReportBase.query.get(request.matchdict['report_id'])
+ 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
+
+ return render_to_response(
+ request,
+ 'mediagoblin/admin/report.html',
+ {'report':report,
+ 'media_entry':media_entry,
+ 'comment':comment})
+
+
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 053f3db2..a32f5932 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -26,7 +26,8 @@ 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, MediaComment, Privilege
+from mediagoblin.db.models import (MediaEntry, Collection, User,
+ MediaComment, Privilege, ReportBase)
MIGRATIONS = {}
@@ -296,6 +297,7 @@ class ReportBase_v0(declarative_base()):
id = Column(Integer, primary_key=True)
reporter_id = Column(Integer, ForeignKey(User.id), nullable=False)
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)
discriminator = Column('type', Unicode(50))
@@ -357,5 +359,3 @@ def create_moderation_tables(db):
Privilege_v0.__table__.create(db.bind)
PrivilegeUserAssociation_v0.__table__.create(db.bind)
db.commit()
-
-
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py
index 9f566e36..70c9dd41 100644
--- a/mediagoblin/db/mixin.py
+++ b/mediagoblin/db/mixin.py
@@ -45,7 +45,6 @@ class UserMixin(object):
def bio_html(self):
return cleaned_markdown_conversion(self.bio)
-
class GenerateSlugMixin(object):
"""
Mixin to add a generate_slug method to objects.
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index e0419c92..e4c97a2c 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -496,8 +496,16 @@ class ReportBase(Base):
User,
backref=backref("reports_filed_by",
lazy="dynamic",
- cascade="all, delete-orphan"))
+ cascade="all, delete-orphan"),
+ primaryjoin="User.id==ReportBase.reporter_id")
report_content = Column(UnicodeText)
+ reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False)
+ reported_user = relationship(
+ User,
+ backref=backref("reports_filed_on",
+ lazy="dynamic",
+ cascade="all, delete-orphan"),
+ primaryjoin="User.id==ReportBase.reported_user_id")
created = Column(DateTime, nullable=False, default=datetime.datetime.now())
resolved = Column(DateTime)
discriminator = Column('type', Unicode(50))
@@ -590,7 +598,7 @@ class PrivilegeUserAssociation(Base):
primary_key=True)
-privilege_foundations = [[u'admin'], [u'moderator'], [u'commenter'], [u'uploader'],[u'reporter'],[u'active']]
+privilege_foundations = [[u'admin'], [u'moderator'], [u'uploader'],[u'reporter'], [u'commenter'] ,[u'active']]
MODELS = [
User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index 206957fa..fefbccef 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -64,7 +64,6 @@ def active_user_from_url(controller):
return wrapper
def user_has_privilege(privilege_name):
-#TODO handle possible errors correctly
def user_has_privilege_decorator(controller):
@wraps(controller)
def wrapper(request, *args, **kwargs):
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 5b8226e6..1cded530 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -346,40 +346,40 @@ textarea#description, textarea#bio {
/* comments */
-.comment_wrapper {
+.comment_wrapper, .report_wrapper {
margin-top: 20px;
margin-bottom: 20px;
}
-.comment_wrapper p {
+.comment_wrapper p, .report_wrapper p {
margin-bottom: 2px;
}
-.comment_author {
+.comment_author, .report_author {
padding-top: 4px;
font-size: 0.9em;
}
-a.comment_authorlink {
+a.comment_authorlink, a.report_authorlink {
text-decoration: none;
padding-right: 5px;
font-weight: bold;
padding-left: 2px;
}
-a.comment_authorlink:hover {
+a.comment_authorlink:hover, a.report_authorlink:hover {
text-decoration: underline;
}
-a.comment_whenlink {
+a.comment_whenlink, a.report_whenlink {
text-decoration: none;
}
-a.comment_whenlink:hover {
+a.comment_whenlink:hover, a.report_whenlink:hover {
text-decoration: underline;
}
-.comment_content {
+.comment_content, .report_content {
margin-left: 8px;
margin-top: 8px;
}
@@ -397,6 +397,11 @@ textarea#comment_content {
padding-right: 6px;
}
+
+a.report_authorlink, a.report_whenlink {
+ color: #D486B1;
+}
+
/* media galleries */
.media_thumbnail {
@@ -597,6 +602,21 @@ table.media_panel th {
text-align: left;
}
+/* admin panels */
+
+table.admin_panel {
+ width: 100%
+}
+
+table.admin_side_panel {
+ width: 60%
+}
+
+table.admin_panel th, table.admin_side_panel th {
+ font-weight: bold;
+ padding-bottom: 4px;
+ text-align: left;
+}
/* Delete panel */
diff --git a/mediagoblin/static/images/icon_clipboard.png b/mediagoblin/static/images/icon_clipboard.png
new file mode 100644
index 00000000..6f94498b
Binary files /dev/null and b/mediagoblin/static/images/icon_clipboard.png differ
diff --git a/mediagoblin/templates/mediagoblin/admin/panel.html b/mediagoblin/templates/mediagoblin/admin/media_panel.html
similarity index 100%
rename from mediagoblin/templates/mediagoblin/admin/panel.html
rename to mediagoblin/templates/mediagoblin/admin/media_panel.html
diff --git a/mediagoblin/templates/mediagoblin/admin/report.html b/mediagoblin/templates/mediagoblin/admin/report.html
index ff5cb427..2e802198 100644
--- a/mediagoblin/templates/mediagoblin/admin/report.html
+++ b/mediagoblin/templates/mediagoblin/admin/report.html
@@ -15,81 +15,76 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#}
-{% extends "mediagoblin/base.html" %}
+{%- extends "mediagoblin/base.html" %}
-{% block title -%}
- {% trans %}Report panel{% endtrans %} — {{ super() }}
-{%- endblock %}
-
-{% block mediagoblin_content %}
-
-{% trans %}Report panel{% endtrans %}
-
-
- {% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
-
-
-{% trans %}Reports Filed on Comments{% endtrans %}
-
-{% if report_list.count() %}
-
+{%- block mediagoblin_content %}
+{% if not report %}
+ Sorry, no such report found.
{% else %}
- {% trans %}No open reports found.{% endtrans %}
+ Report #{{ report.id }}
+ {% if comment %}
+ Reported comment:
+ {% set reported_user = comment.get_author %}
+
+ {% elif media_entry %}
+
+
+ {% endif %}
+ Reason for report:
+
+
+
+ {{ report.report_content }}
+
+
{% endif %}
-{% trans %}Closed Reports on Comments{% endtrans %}
-{% if closed_report_list.count() %}
-
-{% else %}
- {% trans %}No closed reports found.{% endtrans %}
-{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/admin/report_panel.html b/mediagoblin/templates/mediagoblin/admin/report_panel.html
new file mode 100644
index 00000000..30194577
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/admin/report_panel.html
@@ -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 .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block title -%}
+ {% trans %}Report panel{% endtrans %} — {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_content %}
+
+{% trans %}Report panel{% endtrans %}
+
+
+ {% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
+
+
+{% trans %}Reports Filed on Comments{% endtrans %}
+
+{% if report_list.count() %}
+
+
+ ID |
+ Report Type |
+ Offender |
+ When Reported |
+ Reported By |
+ Reason |
+ Reported Comment or Media Entry |
+
+ {% for report in report_list %}
+
+ {% if report.discriminator == "comment_report" %}
+ {{ report.id }} |
+ Comment Report |
+ {{ report.comment.get_author.username }} |
+ {{ report.created.strftime("%F %R") }} |
+ {{ report.reporter.username }} |
+ {{ report.report_content }} |
+ {{ report.comment.get_media_entry.title }} |
+ {% elif report.discriminator == "media_report" %}
+ {{ report.id }} |
+ Media Report |
+ {{ report.media_entry.get_uploader.username }} |
+ {{ report.created.strftime("%F %R") }} |
+ {{ report.reporter.username }} |
+ {{ report.report_content[0:20] }}... |
+ {{ report.media_entry.title }} |
+ {% endif %}
+
+ {% endfor %}
+
+{% else %}
+ {% trans %}No open reports found.{% endtrans %}
+{% endif %}
+{% trans %}Closed Reports on Comments{% endtrans %}
+{% if closed_report_list.count() %}
+
+{% else %}
+ {% trans %}No closed reports found.{% endtrans %}
+{% endif %}
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/admin/user.html b/mediagoblin/templates/mediagoblin/admin/user.html
index 6b6d226a..90b3f583 100644
--- a/mediagoblin/templates/mediagoblin/admin/user.html
+++ b/mediagoblin/templates/mediagoblin/admin/user.html
@@ -17,38 +17,121 @@
#}
{% extends "mediagoblin/base.html" %}
-{% block title -%}
- {% trans %}User panel{% endtrans %} — {{ super() }}
-{%- endblock %}
-{% block mediagoblin_content %}
-
-{% trans %}User panel{% endtrans %}
-
-
- {% trans %}Here you can look up users in order to take punitive actions on them.{% endtrans %}
-
-
-{% trans %}Active Users{% endtrans %}
-
-{% if user_list.count() %}
-
-{% else %}
- {% trans %}No users found.{% endtrans %}
-{% endif %}
+{% block title %}
+ {%- if user -%}
+ {%- trans username=user.username -%}
+ User: {{ username }}
+ {%- endtrans %} — {{ super() }}
+ {%- else -%}
+ {{ super() }}
+ {%- endif -%}
+{% endblock %}
+
+
+{% block mediagoblin_content -%}
+ {# If no user... #}
+ {% if not user %}
+ {% trans %}Sorry, no such user found.{% endtrans %}
+
+ {# User exists, but needs verification #}
+ {% elif user.status == "needs_email_verification" %}
+
+
+ {# Active(?) (or at least verified at some point) user, horray! #}
+ {% else %}
+
+ {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
+
+
+ {% if not user.url and not user.bio %}
+