]> git.openstreetmap.org Git - rails.git/blob - test/controllers/api/changeset_comments_controller_test.rb
Improve testing of changeset comment rate limits
[rails.git] / test / controllers / api / changeset_comments_controller_test.rb
1 require "test_helper"
2
3 module Api
4   class ChangesetCommentsControllerTest < ActionDispatch::IntegrationTest
5     ##
6     # test all routes which lead to this controller
7     def test_routes
8       assert_routing(
9         { :path => "/api/0.6/changeset/1/comment", :method => :post },
10         { :controller => "api/changeset_comments", :action => "create", :id => "1" }
11       )
12       assert_routing(
13         { :path => "/api/0.6/changeset/1/comment.json", :method => :post },
14         { :controller => "api/changeset_comments", :action => "create", :id => "1", :format => "json" }
15       )
16       assert_routing(
17         { :path => "/api/0.6/changeset/comment/1/hide", :method => :post },
18         { :controller => "api/changeset_comments", :action => "destroy", :id => "1" }
19       )
20       assert_routing(
21         { :path => "/api/0.6/changeset/comment/1/hide.json", :method => :post },
22         { :controller => "api/changeset_comments", :action => "destroy", :id => "1", :format => "json" }
23       )
24       assert_routing(
25         { :path => "/api/0.6/changeset/comment/1/unhide", :method => :post },
26         { :controller => "api/changeset_comments", :action => "restore", :id => "1" }
27       )
28       assert_routing(
29         { :path => "/api/0.6/changeset/comment/1/unhide.json", :method => :post },
30         { :controller => "api/changeset_comments", :action => "restore", :id => "1", :format => "json" }
31       )
32     end
33
34     ##
35     # create comment success
36     def test_create_comment_success
37       user = create(:user)
38       user2 = create(:user)
39       private_user = create(:user, :data_public => false)
40       suspended_user = create(:user, :suspended)
41       deleted_user = create(:user, :deleted)
42       private_user_closed_changeset = create(:changeset, :closed, :user => private_user)
43
44       auth_header = basic_authorization_header user.email, "test"
45
46       assert_difference "ChangesetComment.count", 1 do
47         assert_no_difference "ActionMailer::Base.deliveries.size" do
48           perform_enqueued_jobs do
49             post changeset_comment_path(:id => private_user_closed_changeset, :text => "This is a comment"), :headers => auth_header
50           end
51         end
52       end
53       assert_response :success
54
55       changeset = create(:changeset, :closed, :user => private_user)
56       changeset.subscribers.push(private_user)
57       changeset.subscribers.push(user)
58       changeset.subscribers.push(suspended_user)
59       changeset.subscribers.push(deleted_user)
60
61       assert_difference "ChangesetComment.count", 1 do
62         assert_difference "ActionMailer::Base.deliveries.size", 1 do
63           perform_enqueued_jobs do
64             post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
65           end
66         end
67       end
68       assert_response :success
69
70       email = ActionMailer::Base.deliveries.first
71       assert_equal 1, email.to.length
72       assert_equal "[OpenStreetMap] #{user.display_name} has commented on one of your changesets", email.subject
73       assert_equal private_user.email, email.to.first
74
75       ActionMailer::Base.deliveries.clear
76
77       auth_header = basic_authorization_header user2.email, "test"
78
79       assert_difference "ChangesetComment.count", 1 do
80         assert_difference "ActionMailer::Base.deliveries.size", 2 do
81           perform_enqueued_jobs do
82             post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
83           end
84         end
85       end
86       assert_response :success
87
88       email = ActionMailer::Base.deliveries.find { |e| e.to.first == private_user.email }
89       assert_not_nil email
90       assert_equal 1, email.to.length
91       assert_equal "[OpenStreetMap] #{user2.display_name} has commented on one of your changesets", email.subject
92
93       email = ActionMailer::Base.deliveries.find { |e| e.to.first == user.email }
94       assert_not_nil email
95       assert_equal 1, email.to.length
96       assert_equal "[OpenStreetMap] #{user2.display_name} has commented on a changeset you are interested in", email.subject
97
98       ActionMailer::Base.deliveries.clear
99     end
100
101     ##
102     # create comment fail
103     def test_create_comment_fail
104       # unauthorized
105       post changeset_comment_path(:id => create(:changeset, :closed), :text => "This is a comment")
106       assert_response :unauthorized
107
108       auth_header = basic_authorization_header create(:user).email, "test"
109
110       # bad changeset id
111       assert_no_difference "ChangesetComment.count" do
112         post changeset_comment_path(:id => 999111, :text => "This is a comment"), :headers => auth_header
113       end
114       assert_response :not_found
115
116       # not closed changeset
117       assert_no_difference "ChangesetComment.count" do
118         post changeset_comment_path(:id => create(:changeset), :text => "This is a comment"), :headers => auth_header
119       end
120       assert_response :conflict
121
122       # no text
123       assert_no_difference "ChangesetComment.count" do
124         post changeset_comment_path(:id => create(:changeset, :closed)), :headers => auth_header
125       end
126       assert_response :bad_request
127
128       # empty text
129       assert_no_difference "ChangesetComment.count" do
130         post changeset_comment_path(:id => create(:changeset, :closed), :text => ""), :headers => auth_header
131       end
132       assert_response :bad_request
133     end
134
135     ##
136     # create comment rate limit for new users
137     def test_create_comment_new_user_rate_limit
138       changeset = create(:changeset, :closed)
139       user = create(:user)
140
141       auth_header = basic_authorization_header user.email, "test"
142
143       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour do
144         1.upto(Settings.initial_changeset_comments_per_hour) do |count|
145           post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
146           assert_response :success
147         end
148       end
149
150       assert_no_difference "ChangesetComment.count" do
151         post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
152         assert_response :too_many_requests
153       end
154     end
155
156     ##
157     # create comment rate limit for experienced users
158     def test_create_comment_experienced_user_rate_limit
159       changeset = create(:changeset, :closed)
160       user = create(:user)
161       create_list(:changeset_comment, 200, :author_id => user.id, :created_at => Time.now.utc - 1.day)
162
163       auth_header = basic_authorization_header user.email, "test"
164
165       assert_difference "ChangesetComment.count", Settings.max_changeset_comments_per_hour do
166         1.upto(Settings.max_changeset_comments_per_hour) do |count|
167           post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
168           assert_response :success
169         end
170       end
171
172       assert_no_difference "ChangesetComment.count" do
173         post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
174         assert_response :too_many_requests
175       end
176     end
177
178     ##
179     # create comment rate limit for reported users
180     def test_create_comment_reported_user_rate_limit
181       changeset = create(:changeset, :closed)
182       user = create(:user)
183       create(:issue_with_reports, :reportable => user, :reported_user => user)
184
185       auth_header = basic_authorization_header user.email, "test"
186
187       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour / 2 do
188         1.upto(Settings.initial_changeset_comments_per_hour / 2) do |count|
189           post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
190           assert_response :success
191         end
192       end
193
194       assert_no_difference "ChangesetComment.count" do
195         post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
196         assert_response :too_many_requests
197       end
198     end
199
200     ##
201     # create comment rate limit for moderator users
202     def test_create_comment_moderator_user_rate_limit
203       changeset = create(:changeset, :closed)
204       user = create(:moderator_user)
205
206       auth_header = basic_authorization_header user.email, "test"
207
208       assert_difference "ChangesetComment.count", Settings.moderator_changeset_comments_per_hour do
209         1.upto(Settings.moderator_changeset_comments_per_hour) do |count|
210           post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
211           assert_response :success
212         end
213       end
214
215       assert_no_difference "ChangesetComment.count" do
216         post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
217         assert_response :too_many_requests
218       end
219     end
220
221     ##
222     # test hide comment fail
223     def test_destroy_comment_fail
224       # unauthorized
225       comment = create(:changeset_comment)
226       assert comment.visible
227
228       post changeset_comment_hide_path(:id => comment)
229       assert_response :unauthorized
230       assert comment.reload.visible
231
232       auth_header = basic_authorization_header create(:user).email, "test"
233
234       # not a moderator
235       post changeset_comment_hide_path(:id => comment), :headers => auth_header
236       assert_response :forbidden
237       assert comment.reload.visible
238
239       auth_header = basic_authorization_header create(:moderator_user).email, "test"
240
241       # bad comment id
242       post changeset_comment_hide_path(:id => 999111), :headers => auth_header
243       assert_response :not_found
244       assert comment.reload.visible
245     end
246
247     ##
248     # test hide comment succes
249     def test_hide_comment_success
250       comment = create(:changeset_comment)
251       assert comment.visible
252
253       auth_header = basic_authorization_header create(:moderator_user).email, "test"
254
255       post changeset_comment_hide_path(:id => comment), :headers => auth_header
256       assert_response :success
257       assert_not comment.reload.visible
258     end
259
260     ##
261     # test unhide comment fail
262     def test_restore_comment_fail
263       # unauthorized
264       comment = create(:changeset_comment, :visible => false)
265       assert_not comment.visible
266
267       post changeset_comment_unhide_path(:id => comment)
268       assert_response :unauthorized
269       assert_not comment.reload.visible
270
271       auth_header = basic_authorization_header create(:user).email, "test"
272
273       # not a moderator
274       post changeset_comment_unhide_path(:id => comment), :headers => auth_header
275       assert_response :forbidden
276       assert_not comment.reload.visible
277
278       auth_header = basic_authorization_header create(:moderator_user).email, "test"
279
280       # bad comment id
281       post changeset_comment_unhide_path(:id => 999111), :headers => auth_header
282       assert_response :not_found
283       assert_not comment.reload.visible
284     end
285
286     ##
287     # test unhide comment succes
288     def test_unhide_comment_success
289       comment = create(:changeset_comment, :visible => false)
290       assert_not comment.visible
291
292       auth_header = basic_authorization_header create(:moderator_user).email, "test"
293
294       post changeset_comment_unhide_path(:id => comment), :headers => auth_header
295       assert_response :success
296       assert comment.reload.visible
297     end
298
299     # This test ensures that token capabilities behave correctly for a method that
300     # requires the terms to have been agreed.
301     # (This would be better as an integration or system testcase, since the changeset_comment
302     # create method is simply a stand-in for any method that requires terms agreement.
303     # But writing oauth tests is hard, and so it's easier to put in a controller test.)
304     def test_api_write_and_terms_agreed_via_token
305       user = create(:user, :terms_agreed => nil)
306       token = create(:access_token, :user => user, :allow_write_api => true)
307       changeset = create(:changeset, :closed)
308
309       assert_difference "ChangesetComment.count", 0 do
310         signed_post changeset_comment_path(:id => changeset), :params => { :text => "This is a comment" }, :oauth => { :token => token }
311       end
312       assert_response :forbidden
313
314       # Try again, after agreement with the terms
315       user.terms_agreed = Time.now.utc
316       user.save!
317
318       assert_difference "ChangesetComment.count", 1 do
319         signed_post changeset_comment_path(:id => changeset), :params => { :text => "This is a comment" }, :oauth => { :token => token }
320       end
321       assert_response :success
322     end
323
324     # This test does the same as above, but with basic auth, to similarly test that the
325     # abilities take into account terms agreement too.
326     def test_api_write_and_terms_agreed_via_basic_auth
327       user = create(:user, :terms_agreed => nil)
328       changeset = create(:changeset, :closed)
329
330       auth_header = basic_authorization_header user.email, "test"
331
332       assert_difference "ChangesetComment.count", 0 do
333         post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
334       end
335       assert_response :forbidden
336
337       # Try again, after agreement with the terms
338       user.terms_agreed = Time.now.utc
339       user.save!
340
341       assert_difference "ChangesetComment.count", 1 do
342         post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
343       end
344       assert_response :success
345     end
346   end
347 end