]> git.openstreetmap.org Git - rails.git/blob - test/controllers/api/changeset_comments_controller_test.rb
Add rate limiting for changeset comments
[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
137     def test_create_comment_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.min_changeset_comments_per_hour do
144         1.upto(Settings.min_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     # test hide comment fail
158     def test_destroy_comment_fail
159       # unauthorized
160       comment = create(:changeset_comment)
161       assert comment.visible
162
163       post changeset_comment_hide_path(:id => comment)
164       assert_response :unauthorized
165       assert comment.reload.visible
166
167       auth_header = basic_authorization_header create(:user).email, "test"
168
169       # not a moderator
170       post changeset_comment_hide_path(:id => comment), :headers => auth_header
171       assert_response :forbidden
172       assert comment.reload.visible
173
174       auth_header = basic_authorization_header create(:moderator_user).email, "test"
175
176       # bad comment id
177       post changeset_comment_hide_path(:id => 999111), :headers => auth_header
178       assert_response :not_found
179       assert comment.reload.visible
180     end
181
182     ##
183     # test hide comment succes
184     def test_hide_comment_success
185       comment = create(:changeset_comment)
186       assert comment.visible
187
188       auth_header = basic_authorization_header create(:moderator_user).email, "test"
189
190       post changeset_comment_hide_path(:id => comment), :headers => auth_header
191       assert_response :success
192       assert_not comment.reload.visible
193     end
194
195     ##
196     # test unhide comment fail
197     def test_restore_comment_fail
198       # unauthorized
199       comment = create(:changeset_comment, :visible => false)
200       assert_not comment.visible
201
202       post changeset_comment_unhide_path(:id => comment)
203       assert_response :unauthorized
204       assert_not comment.reload.visible
205
206       auth_header = basic_authorization_header create(:user).email, "test"
207
208       # not a moderator
209       post changeset_comment_unhide_path(:id => comment), :headers => auth_header
210       assert_response :forbidden
211       assert_not comment.reload.visible
212
213       auth_header = basic_authorization_header create(:moderator_user).email, "test"
214
215       # bad comment id
216       post changeset_comment_unhide_path(:id => 999111), :headers => auth_header
217       assert_response :not_found
218       assert_not comment.reload.visible
219     end
220
221     ##
222     # test unhide comment succes
223     def test_unhide_comment_success
224       comment = create(:changeset_comment, :visible => false)
225       assert_not comment.visible
226
227       auth_header = basic_authorization_header create(:moderator_user).email, "test"
228
229       post changeset_comment_unhide_path(:id => comment), :headers => auth_header
230       assert_response :success
231       assert comment.reload.visible
232     end
233
234     # This test ensures that token capabilities behave correctly for a method that
235     # requires the terms to have been agreed.
236     # (This would be better as an integration or system testcase, since the changeset_comment
237     # create method is simply a stand-in for any method that requires terms agreement.
238     # But writing oauth tests is hard, and so it's easier to put in a controller test.)
239     def test_api_write_and_terms_agreed_via_token
240       user = create(:user, :terms_agreed => nil)
241       token = create(:access_token, :user => user, :allow_write_api => true)
242       changeset = create(:changeset, :closed)
243
244       assert_difference "ChangesetComment.count", 0 do
245         signed_post changeset_comment_path(:id => changeset), :params => { :text => "This is a comment" }, :oauth => { :token => token }
246       end
247       assert_response :forbidden
248
249       # Try again, after agreement with the terms
250       user.terms_agreed = Time.now.utc
251       user.save!
252
253       assert_difference "ChangesetComment.count", 1 do
254         signed_post changeset_comment_path(:id => changeset), :params => { :text => "This is a comment" }, :oauth => { :token => token }
255       end
256       assert_response :success
257     end
258
259     # This test does the same as above, but with basic auth, to similarly test that the
260     # abilities take into account terms agreement too.
261     def test_api_write_and_terms_agreed_via_basic_auth
262       user = create(:user, :terms_agreed => nil)
263       changeset = create(:changeset, :closed)
264
265       auth_header = basic_authorization_header user.email, "test"
266
267       assert_difference "ChangesetComment.count", 0 do
268         post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
269       end
270       assert_response :forbidden
271
272       # Try again, after agreement with the terms
273       user.terms_agreed = Time.now.utc
274       user.save!
275
276       assert_difference "ChangesetComment.count", 1 do
277         post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
278       end
279       assert_response :success
280     end
281   end
282 end