This was a big commit! I included lots of documentation below, but generally I
[mediagoblin.git] / mediagoblin / tests / test_moderation.py
CommitLineData
dfd66b78 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
17import pytest
18
19from mediagoblin.tests.tools import (fixture_add_user,
20 fixture_add_comment_report, fixture_add_comment)
21from mediagoblin.db.models import User, CommentReport, MediaComment, UserBan
22from mediagoblin.moderation.tools import take_away_privileges, give_privileges
23from mediagoblin.tools import template, mail
24
25from webtest import AppError
26
27class TestModerationViews:
28 @pytest.fixture(autouse=True)
29 def _setup(self, test_app):
30 self.test_app = test_app
31
32 fixture_add_user(u'admin',
33 privileges=[u'admin',u'active'])
34 fixture_add_user(u'moderator',
35 privileges=[u'moderator',u'active'])
36 fixture_add_user(u'regular',
37 privileges=[u'active',u'commenter'])
38 self.query_for_users()
39
40 def login(self, username):
41 self.test_app.post(
42 '/auth/login/', {
43 'username': username,
44 'password': 'toast'})
45 self.query_for_users()
46
47 def logout(self):
48 self.test_app.get('/auth/logout/')
49 self.query_for_users()
50
51 def query_for_users(self):
52 self.admin_user = User.query.filter(User.username==u'admin').first()
53 self.mod_user = User.query.filter(User.username==u'moderator').first()
54 self.user = User.query.filter(User.username==u'regular').first()
55
56 def do_post(self, data, *context_keys, **kwargs):
57 url = kwargs.pop('url', '/submit/')
58 do_follow = kwargs.pop('do_follow', False)
59 template.clear_test_template_context()
60 response = self.test_app.post(url, data, **kwargs)
61 if do_follow:
62 response.follow()
63 context_data = template.TEMPLATE_TEST_CONTEXT
64 for key in context_keys:
65 context_data = context_data[key]
66 return response, context_data
67
68 def testGiveOrTakeAwayPrivileges(self):
69 self.login(u'admin')
70 # First, test an admin taking away a privilege from a user
71 #----------------------------------------------------------------------
72 response, context = self.do_post({'privilege_name':u'commenter'},
73 url='/mod/users/{0}/privilege/'.format(self.user.username))
74 assert response.status == '302 FOUND'
75 self.query_for_users()
76 assert not self.user.has_privilege(u'commenter')
77
78 # Then, test an admin giving a privilege to a user
79 #----------------------------------------------------------------------
80 response, context = self.do_post({'privilege_name':u'commenter'},
81 url='/mod/users/{0}/privilege/'.format(self.user.username))
82 assert response.status == '302 FOUND'
83 self.query_for_users()
84 assert self.user.has_privilege(u'commenter')
85
86 # Then, test a mod trying to take away a privilege from a user
87 # they are not allowed to do this, so this will raise an error
88 #----------------------------------------------------------------------
89 self.logout()
90 self.login(u'moderator')
91
92 with pytest.raises(AppError) as excinfo:
93 response, context = self.do_post({'privilege_name':u'commenter'},
94 url='/mod/users/{0}/privilege/'.format(self.user.username))
95 assert 'Bad response: 403 FORBIDDEN' in str(excinfo)
96 self.query_for_users()
97
98 assert self.user.has_privilege(u'commenter')
99
100 def testReportResolution(self):
101 self.login(u'moderator')
102
103 # First, test a moderators taking away a user's privilege in response
104 # to a reported comment
105 #----------------------------------------------------------------------
106 fixture_add_comment_report(reported_user=self.user)
107 comment_report = CommentReport.query.filter(
108 CommentReport.reported_user==self.user).first()
109
110 response = self.test_app.get('/mod/reports/{0}/'.format(
111 comment_report.id))
112 assert response.status == '200 OK'
113 self.query_for_users()
114 comment_report = CommentReport.query.filter(
115 CommentReport.reported_user==self.user).first()
116
117 response, context = self.do_post({'action_to_resolve':[u'takeaway'],
118 'take_away_privileges':[u'commenter'],
119 'targeted_user':self.user.id},
120 url='/mod/reports/{0}/'.format(comment_report.id))
121
122 assert response.status == '302 FOUND'
123 fixture_add_comment_report(reported_user=self.user)
124 comment_report = CommentReport.query.filter(
125 CommentReport.reported_user==self.user).first()
126
127 assert not self.user.has_privilege(u'commenter')
128
129 # Then, test a moderator sending an email to a user in response to a
130 # reported comment
131 #----------------------------------------------------------------------
132 self.query_for_users()
133
134 response, context = self.do_post({'action_to_resolve':[u'sendmessage'],
135 'message_to_user':'This is your last warning, regular....',
136 'targeted_user':self.user.id},
137 url='/mod/reports/{0}/'.format(comment_report.id))
138
139 assert response.status == '302 FOUND'
140 assert mail.EMAIL_TEST_MBOX_INBOX == [{'to': [u'regular@example.com'],
141 'message': 'Content-Type: text/plain; charset="utf-8"\n\
142MIME-Version: 1.0\nContent-Transfer-Encoding: base64\nSubject: Warning from- \
143moderator \nFrom: notice@mediagoblin.example.org\nTo: regular@example.com\n\n\
144VGhpcyBpcyB5b3VyIGxhc3Qgd2FybmluZywgcmVndWxhci4uLi4=\n',
145 'from': 'notice@mediagoblin.example.org'}]
146
147 # Then test a moderator banning a user AND a moderator deleting the
148 # offending comment. This also serves as a test for taking multiple
149 # actions to resolve a report
150 #----------------------------------------------------------------------
151 self.query_for_users()
152 fixture_add_comment(author=self.user.id,
153 comment=u'Comment will be removed')
154 test_comment = MediaComment.query.filter(
155 MediaComment.author==self.user.id).first()
156 fixture_add_comment_report(comment=test_comment,
157 reported_user=self.user)
158 comment_report = CommentReport.query.filter(
159 CommentReport.reported_user==self.user).first()
160
161 response, context = self.do_post(
162 {'action_to_resolve':[u'userban', u'delete'],
163 'targeted_user':self.user.id},
164 url='/mod/reports/{0}/'.format(comment_report.id))
165 assert response.status == '302 FOUND'
166 self.query_for_users()
167 test_user_ban = UserBan.query.filter(
168 UserBan.user_id == self.user.id).first()
169 assert test_user_ban is not None
170 test_comment = MediaComment.query.filter(
171 MediaComment.author==self.user.id).first()
172 assert test_comment is None
173
174 # Then, test what happens when a moderator attempts to punish an admin
175 # from a reported comment on an admin.
176 #----------------------------------------------------------------------
177 fixture_add_comment_report(reported_user=self.admin_user)
178 comment_report = CommentReport.query.filter(
179 CommentReport.reported_user==self.admin_user).first()
180
181 response, context = self.do_post({'action_to_resolve':[u'takeaway'],
182 'take_away_privileges':[u'active'],
183 'targeted_user':self.admin_user.id},
184 url='/mod/reports/{0}/'.format(comment_report.id))
185 self.query_for_users()
186
187 assert response.status == '200 OK'
188 assert self.admin_user.has_privilege(u'active')
189
190 def testAllModerationViews(self):
191 self.login(u'moderator')
192 self.test_app.get('/mod/reports/')
193 self.test_app.get('/mod/users/')
194 self.test_app.get('/mod/media/')