At this point, I am very close to done with this code! I made one big change at
[mediagoblin:mediagoblin.git] / mediagoblin / moderation / views.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors.  See AUTHORS.
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 from werkzeug.exceptions import Forbidden
18
19 from mediagoblin.db.models import (MediaEntry, User, MediaComment, \
20                                    CommentReport, ReportBase, Privilege, \
21                                    UserBan)
22 from mediagoblin.decorators import (require_admin_or_moderator_login, 
23                                     active_user_from_url, user_has_privilege,
24                                     allow_reporting)
25 from mediagoblin.tools.response import render_to_response, redirect
26 from mediagoblin.moderation import forms as moderation_forms
27 from mediagoblin.moderation.tools import (take_punitive_actions, \
28     take_away_privileges, give_privileges, ban_user, unban_user, \
29     parse_report_panel_settings)
30 from werkzeug.datastructures import ImmutableMultiDict
31 from datetime import datetime
32 from math import ceil
33
34 @require_admin_or_moderator_login
35 def moderation_media_processing_panel(request):
36     '''
37     Show the global media processing panel for this instance
38     '''
39     processing_entries = MediaEntry.query.filter_by(state = u'processing').\
40         order_by(MediaEntry.created.desc())
41
42     # Get media entries which have failed to process
43     failed_entries = MediaEntry.query.filter_by(state = u'failed').\
44         order_by(MediaEntry.created.desc())
45
46     processed_entries = MediaEntry.query.filter_by(state = u'processed').\
47         order_by(MediaEntry.created.desc()).limit(10)
48
49     # Render to response
50     return render_to_response(
51         request,
52         'mediagoblin/moderation/media_panel.html',
53         {'processing_entries': processing_entries,
54          'failed_entries': failed_entries,
55          'processed_entries': processed_entries})
56
57 @require_admin_or_moderator_login
58 def moderation_users_panel(request):
59     '''
60     Show the global panel for monitoring users in this instance
61     '''
62     current_page = 1
63     if len(request.args) > 0:
64         form = moderation_forms.UserPanelSortingForm(request.args)
65         if form.validate():
66             current_page = form.p.data or 1
67
68     all_user_list = User.query
69     user_list = all_user_list.order_by(
70         User.created.desc()).offset(
71             (current_page-1)*10).limit(10)
72     last_page = int(ceil(all_user_list.count()/10.))
73
74     return render_to_response(
75         request,
76         'mediagoblin/moderation/user_panel.html',
77         {'user_list': user_list,
78          'current_page':current_page,
79          'last_page':last_page})
80
81 @require_admin_or_moderator_login
82 def moderation_users_detail(request):
83     '''
84     Shows details about a particular user.
85     '''
86     user = User.query.filter_by(username=request.matchdict['user']).first()
87     active_reports = user.reports_filed_on.filter(
88         ReportBase.resolved==None).limit(5)
89     closed_reports = user.reports_filed_on.filter(
90         ReportBase.resolved!=None).all()
91     privileges = Privilege.query
92     user_banned = UserBan.query.get(user.id)
93     ban_form = moderation_forms.BanForm()
94
95     return render_to_response(
96         request,
97         'mediagoblin/moderation/user.html',
98         {'user':user,
99          'privileges': privileges,
100          'reports':active_reports,
101          'user_banned':user_banned,
102          'ban_form':ban_form})
103
104 @require_admin_or_moderator_login
105 @allow_reporting
106 def moderation_reports_panel(request):
107     '''
108     Show the global panel for monitoring reports filed against comments or
109         media entries for this instance.
110     '''
111     filters = []
112     active_settings, closed_settings = {'current_page':1}, {'current_page':1}
113
114     if len(request.args) > 0:
115         form = moderation_forms.ReportPanelSortingForm(request.args)
116         if form.validate():
117             filters = parse_report_panel_settings(form)
118             active_settings['current_page'] = form.active_p.data or 1
119             closed_settings['current_page'] = form.closed_p.data or 1
120             filters = [
121                getattr(ReportBase,key)==val
122                for key,val in filters.viewitems()]
123
124     all_active = ReportBase.query.filter(
125         ReportBase.resolved==None).filter(
126         *filters)
127     all_closed = ReportBase.query.filter(
128         ReportBase.resolved!=None).filter(
129         *filters)
130
131     # report_list and closed_report_list are the two lists of up to 10
132     # items which are actually passed to the user in this request
133     report_list = all_active.order_by(
134         ReportBase.created.desc()).offset(
135             (active_settings['current_page']-1)*10).limit(10)
136     closed_report_list = all_closed.order_by(
137         ReportBase.created.desc()).offset(
138             (closed_settings['current_page']-1)*10).limit(10)
139
140     active_settings['last_page'] = int(ceil(all_active.count()/10.))
141     closed_settings['last_page'] = int(ceil(all_closed.count()/10.))
142     # Render to response
143     return render_to_response(
144         request,
145         'mediagoblin/moderation/report_panel.html',
146         {'report_list':report_list,
147          'closed_report_list':closed_report_list,
148          'active_settings':active_settings,
149          'closed_settings':closed_settings})
150
151 @require_admin_or_moderator_login
152 @allow_reporting
153 def moderation_reports_detail(request):
154     """
155     This is the page an admin or moderator goes to see the details of a report.
156     The report can be resolved or unresolved. This is also the page that a mod-
157     erator would go to to take an action to resolve a report.
158     """
159     form = moderation_forms.ReportResolutionForm(request.form)
160     report = ReportBase.query.get(request.matchdict['report_id'])
161
162     form.take_away_privileges.choices = [
163         (s.privilege_name,s.privilege_name.title()) \
164             for s in report.reported_user.all_privileges
165     ]
166
167     if request.method == "POST" and form.validate() and not (
168         not request.user.has_privilege(u'admin') and
169         report.reported_user.has_privilege(u'admin')):
170
171         user = User.query.get(form.targeted_user.data)
172         return take_punitive_actions(request, form, report, user)
173
174
175     form.targeted_user.data = report.reported_user_id
176
177     return render_to_response(
178         request,
179         'mediagoblin/moderation/report.html',
180         {'report':report,
181          'form':form})
182
183 @user_has_privilege(u'admin')
184 @active_user_from_url
185 def give_or_take_away_privilege(request, url_user):
186     '''
187     A form action to give or take away a particular privilege from a user.
188     Can only be used by an admin.
189     '''
190     form = moderation_forms.PrivilegeAddRemoveForm(request.form)
191     if request.method == "POST" and form.validate():
192         privilege = Privilege.query.filter(
193             Privilege.privilege_name==form.privilege_name.data).one()
194         if not take_away_privileges(
195             url_user.username, form.privilege_name.data):
196
197             give_privileges(url_user.username, form.privilege_name.data)
198         url_user.save()
199
200     return redirect(
201         request,
202         'mediagoblin.moderation.users_detail',
203         user=url_user.username)
204
205 @user_has_privilege(u'admin')
206 @active_user_from_url
207 def ban_or_unban(request, url_user):
208     """
209     A page to ban or unban a user. Only can be used by an admin.
210     """
211     form = moderation_forms.BanForm(request.form)
212     if request.method == "POST" and form.validate():
213         already_banned = unban_user(url_user.id)
214         same_as_requesting_user = (request.user.id == url_user.id)
215         if not already_banned and not same_as_requesting_user:
216             user_ban = ban_user(url_user.id,
217                 expiration_date = form.user_banned_until.data,
218                 reason = form.why_user_was_banned.data)
219             user_ban.save()
220     return redirect(
221         request,
222         'mediagoblin.moderation.users_detail',
223         user=url_user.username)