]> git.openstreetmap.org Git - rails.git/blob - test/controllers/api/old_ways_controller_test.rb
Merge pull request #4502 from tomhughes/oauth2-authorization-time
[rails.git] / test / controllers / api / old_ways_controller_test.rb
1 require "test_helper"
2
3 module Api
4   class OldWaysControllerTest < ActionDispatch::IntegrationTest
5     ##
6     # test all routes which lead to this controller
7     def test_routes
8       assert_routing(
9         { :path => "/api/0.6/way/1/history", :method => :get },
10         { :controller => "api/old_ways", :action => "history", :id => "1" }
11       )
12       assert_routing(
13         { :path => "/api/0.6/way/1/2", :method => :get },
14         { :controller => "api/old_ways", :action => "version", :id => "1", :version => "2" }
15       )
16       assert_routing(
17         { :path => "/api/0.6/way/1/history.json", :method => :get },
18         { :controller => "api/old_ways", :action => "history", :id => "1", :format => "json" }
19       )
20       assert_routing(
21         { :path => "/api/0.6/way/1/2.json", :method => :get },
22         { :controller => "api/old_ways", :action => "version", :id => "1", :version => "2", :format => "json" }
23       )
24       assert_routing(
25         { :path => "/api/0.6/way/1/2/redact", :method => :post },
26         { :controller => "api/old_ways", :action => "redact", :id => "1", :version => "2" }
27       )
28     end
29
30     # -------------------------------------
31     # Test reading old ways.
32     # -------------------------------------
33
34     def test_history_visible
35       # check that a visible way is returned properly
36       get api_way_history_path(create(:way, :with_history))
37       assert_response :success
38     end
39
40     def test_history_invisible
41       # check that an invisible way's history is returned properly
42       get api_way_history_path(create(:way, :with_history, :deleted))
43       assert_response :success
44     end
45
46     def test_history_invalid
47       # check chat a non-existent way is not returned
48       get api_way_history_path(:id => 0)
49       assert_response :not_found
50     end
51
52     ##
53     # check that we can retrieve versions of a way
54     def test_version
55       way = create(:way, :with_history)
56       used_way = create(:way, :with_history)
57       create(:relation_member, :member => used_way)
58       way_with_versions = create(:way, :with_history, :version => 4)
59
60       create(:way_tag, :way => way)
61       create(:way_tag, :way => used_way)
62       create(:way_tag, :way => way_with_versions)
63       propagate_tags(way, way.old_ways.last)
64       propagate_tags(used_way, used_way.old_ways.last)
65       propagate_tags(way_with_versions, way_with_versions.old_ways.last)
66
67       check_current_version(way.id)
68       check_current_version(used_way.id)
69       check_current_version(way_with_versions.id)
70     end
71
72     ##
73     # check that returned history is the same as getting all
74     # versions of a way from the api.
75     def test_history_equals_versions
76       way = create(:way, :with_history)
77       used_way = create(:way, :with_history)
78       create(:relation_member, :member => used_way)
79       way_with_versions = create(:way, :with_history, :version => 4)
80
81       check_history_equals_versions(way.id)
82       check_history_equals_versions(used_way.id)
83       check_history_equals_versions(way_with_versions.id)
84     end
85
86     ##
87     # test the redaction of an old version of a way, while not being
88     # authorised.
89     def test_redact_way_unauthorised
90       way = create(:way, :with_history, :version => 4)
91       way_v3 = way.old_ways.find_by(:version => 3)
92
93       do_redact_way(way_v3, create(:redaction))
94       assert_response :unauthorized, "should need to be authenticated to redact."
95     end
96
97     ##
98     # test the redaction of an old version of a way, while being
99     # authorised as a normal user.
100     def test_redact_way_normal_user
101       auth_header = basic_authorization_header create(:user).email, "test"
102       way = create(:way, :with_history, :version => 4)
103       way_v3 = way.old_ways.find_by(:version => 3)
104
105       do_redact_way(way_v3, create(:redaction), auth_header)
106       assert_response :forbidden, "should need to be moderator to redact."
107     end
108
109     ##
110     # test that, even as moderator, the current version of a way
111     # can't be redacted.
112     def test_redact_way_current_version
113       auth_header = basic_authorization_header create(:moderator_user).email, "test"
114       way = create(:way, :with_history, :version => 4)
115       way_latest = way.old_ways.last
116
117       do_redact_way(way_latest, create(:redaction), auth_header)
118       assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
119     end
120
121     def test_redact_way_by_regular_with_read_prefs_scope
122       auth_header = create_bearer_auth_header(create(:user), %w[read_prefs])
123       do_redact_redactable_way(auth_header)
124       assert_response :forbidden, "should need to be moderator to redact."
125     end
126
127     def test_redact_way_by_regular_with_write_api_scope
128       auth_header = create_bearer_auth_header(create(:user), %w[write_api])
129       do_redact_redactable_way(auth_header)
130       assert_response :forbidden, "should need to be moderator to redact."
131     end
132
133     def test_redact_way_by_regular_with_write_redactions_scope
134       auth_header = create_bearer_auth_header(create(:user), %w[write_redactions])
135       do_redact_redactable_way(auth_header)
136       assert_response :forbidden, "should need to be moderator to redact."
137     end
138
139     def test_redact_way_by_moderator_with_read_prefs_scope
140       auth_header = create_bearer_auth_header(create(:moderator_user), %w[read_prefs])
141       do_redact_redactable_way(auth_header)
142       assert_response :forbidden, "should need to have write_redactions scope to redact."
143     end
144
145     def test_redact_way_by_moderator_with_write_api_scope
146       auth_header = create_bearer_auth_header(create(:moderator_user), %w[write_api])
147       do_redact_redactable_way(auth_header)
148       assert_response :success, "should be OK to redact old version as moderator with write_api scope."
149       # assert_response :forbidden, "should need to have write_redactions scope to redact."
150     end
151
152     def test_redact_way_by_moderator_with_write_redactions_scope
153       auth_header = create_bearer_auth_header(create(:moderator_user), %w[write_redactions])
154       do_redact_redactable_way(auth_header)
155       assert_response :success, "should be OK to redact old version as moderator with write_redactions scope."
156     end
157
158     ##
159     # test that redacted ways aren't visible, regardless of
160     # authorisation except as moderator...
161     def test_version_redacted
162       way = create(:way, :with_history, :version => 2)
163       way_v1 = way.old_ways.find_by(:version => 1)
164       way_v1.redact!(create(:redaction))
165
166       get way_version_path(:id => way_v1.way_id, :version => way_v1.version)
167       assert_response :forbidden, "Redacted way shouldn't be visible via the version API."
168
169       # not even to a logged-in user
170       auth_header = basic_authorization_header create(:user).email, "test"
171       get way_version_path(:id => way_v1.way_id, :version => way_v1.version), :headers => auth_header
172       assert_response :forbidden, "Redacted way shouldn't be visible via the version API, even when logged in."
173     end
174
175     ##
176     # test that redacted ways aren't visible in the history
177     def test_history_redacted
178       way = create(:way, :with_history, :version => 2)
179       way_v1 = way.old_ways.find_by(:version => 1)
180       way_v1.redact!(create(:redaction))
181
182       get api_way_history_path(:id => way_v1.way_id)
183       assert_response :success, "Redaction shouldn't have stopped history working."
184       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
185                     "redacted way #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history."
186
187       # not even to a logged-in user
188       auth_header = basic_authorization_header create(:user).email, "test"
189       get way_version_path(:id => way_v1.way_id, :version => way_v1.version), :headers => auth_header
190       get api_way_history_path(:id => way_v1.way_id), :headers => auth_header
191       assert_response :success, "Redaction shouldn't have stopped history working."
192       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
193                     "redacted node #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history, even when logged in."
194     end
195
196     ##
197     # test the redaction of an old version of a way, while being
198     # authorised as a moderator.
199     def test_redact_way_moderator
200       way = create(:way, :with_history, :version => 4)
201       way_v3 = way.old_ways.find_by(:version => 3)
202       auth_header = basic_authorization_header create(:moderator_user).email, "test"
203
204       do_redact_way(way_v3, create(:redaction), auth_header)
205       assert_response :success, "should be OK to redact old version as moderator."
206
207       # check moderator can still see the redacted data, when passing
208       # the appropriate flag
209       get way_version_path(:id => way_v3.way_id, :version => way_v3.version), :headers => auth_header
210       assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
211       get way_version_path(:id => way_v3.way_id, :version => way_v3.version), :params => { :show_redactions => "true" }, :headers => auth_header
212       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
213
214       # and when accessed via history
215       get api_way_history_path(:id => way_v3.way_id), :headers => auth_header
216       assert_response :success, "Redaction shouldn't have stopped history working."
217       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 0,
218                     "way #{way_v3.way_id} version #{way_v3.version} should not be present in the history for moderators when not passing flag."
219       get api_way_history_path(:id => way_v3.way_id), :params => { :show_redactions => "true" }, :headers => auth_header
220       assert_response :success, "Redaction shouldn't have stopped history working."
221       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 1,
222                     "way #{way_v3.way_id} version #{way_v3.version} should still be present in the history for moderators when passing flag."
223     end
224
225     # testing that if the moderator drops auth, he can't see the
226     # redacted stuff any more.
227     def test_redact_way_is_redacted
228       way = create(:way, :with_history, :version => 4)
229       way_v3 = way.old_ways.find_by(:version => 3)
230       auth_header = basic_authorization_header create(:moderator_user).email, "test"
231
232       do_redact_way(way_v3, create(:redaction), auth_header)
233       assert_response :success, "should be OK to redact old version as moderator."
234
235       # re-auth as non-moderator
236       auth_header = basic_authorization_header create(:user).email, "test"
237
238       # check can't see the redacted data
239       get way_version_path(:id => way_v3.way_id, :version => way_v3.version), :headers => auth_header
240       assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
241
242       # and when accessed via history
243       get api_way_history_path(:id => way_v3.way_id), :headers => auth_header
244       assert_response :success, "Redaction shouldn't have stopped history working."
245       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 0,
246                     "redacted way #{way_v3.way_id} version #{way_v3.version} shouldn't be present in the history."
247     end
248
249     ##
250     # test the unredaction of an old version of a way, while not being
251     # authorised.
252     def test_unredact_way_unauthorised
253       way = create(:way, :with_history, :version => 2)
254       way_v1 = way.old_ways.find_by(:version => 1)
255       way_v1.redact!(create(:redaction))
256
257       post way_version_redact_path(:id => way_v1.way_id, :version => way_v1.version)
258       assert_response :unauthorized, "should need to be authenticated to unredact."
259     end
260
261     ##
262     # test the unredaction of an old version of a way, while being
263     # authorised as a normal user.
264     def test_unredact_way_normal_user
265       way = create(:way, :with_history, :version => 2)
266       way_v1 = way.old_ways.find_by(:version => 1)
267       way_v1.redact!(create(:redaction))
268
269       auth_header = basic_authorization_header create(:user).email, "test"
270
271       post way_version_redact_path(:id => way_v1.way_id, :version => way_v1.version), :headers => auth_header
272       assert_response :forbidden, "should need to be moderator to unredact."
273     end
274
275     ##
276     # test the unredaction of an old version of a way, while being
277     # authorised as a moderator.
278     def test_unredact_way_moderator
279       moderator_user = create(:moderator_user)
280       way = create(:way, :with_history, :version => 2)
281       way_v1 = way.old_ways.find_by(:version => 1)
282       way_v1.redact!(create(:redaction))
283
284       auth_header = basic_authorization_header moderator_user.email, "test"
285
286       post way_version_redact_path(:id => way_v1.way_id, :version => way_v1.version), :headers => auth_header
287       assert_response :success, "should be OK to unredact old version as moderator."
288
289       # check moderator can still see the unredacted data, without passing
290       # the appropriate flag
291       get way_version_path(:id => way_v1.way_id, :version => way_v1.version), :headers => auth_header
292       assert_response :success, "After unredaction, node should not be gone for moderator."
293
294       # and when accessed via history
295       get api_way_history_path(:id => way_v1.way_id), :headers => auth_header
296       assert_response :success, "Unredaction shouldn't have stopped history working."
297       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 1,
298                     "way #{way_v1.way_id} version #{way_v1.version} should still be present in the history for moderators."
299
300       auth_header = basic_authorization_header create(:user).email, "test"
301
302       # check normal user can now see the unredacted data
303       get way_version_path(:id => way_v1.way_id, :version => way_v1.version), :headers => auth_header
304       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
305
306       # and when accessed via history
307       get api_way_history_path(:id => way_v1.way_id), :headers => auth_header
308       assert_response :success, "Redaction shouldn't have stopped history working."
309       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 1,
310                     "way #{way_v1.way_id} version #{way_v1.version} should still be present in the history for normal users."
311     end
312
313     private
314
315     ##
316     # check that the current version of a way is equivalent to the
317     # version which we're getting from the versions call.
318     def check_current_version(way_id)
319       # get the current version
320       current_way = with_controller(WaysController.new) do
321         get api_way_path(way_id)
322         assert_response :success, "can't get current way #{way_id}"
323         Way.from_xml(@response.body)
324       end
325       assert_not_nil current_way, "getting way #{way_id} returned nil"
326
327       # get the "old" version of the way from the version method
328       get way_version_path(:id => way_id, :version => current_way.version)
329       assert_response :success, "can't get old way #{way_id}, v#{current_way.version}"
330       old_way = Way.from_xml(@response.body)
331
332       # check that the ways are identical
333       assert_ways_are_equal current_way, old_way
334     end
335
336     ##
337     # look at all the versions of the way in the history and get each version from
338     # the versions call. check that they're the same.
339     def check_history_equals_versions(way_id)
340       get api_way_history_path(:id => way_id)
341       assert_response :success, "can't get way #{way_id} from API"
342       history_doc = XML::Parser.string(@response.body).parse
343       assert_not_nil history_doc, "parsing way #{way_id} history failed"
344
345       history_doc.find("//osm/way").each do |way_doc|
346         history_way = Way.from_xml_node(way_doc)
347         assert_not_nil history_way, "parsing way #{way_id} version failed"
348
349         get way_version_path(:id => way_id, :version => history_way.version)
350         assert_response :success, "couldn't get way #{way_id}, v#{history_way.version}"
351         version_way = Way.from_xml(@response.body)
352         assert_not_nil version_way, "failed to parse #{way_id}, v#{history_way.version}"
353
354         assert_ways_are_equal history_way, version_way
355       end
356     end
357
358     def create_bearer_auth_header(user, scopes)
359       token = create(:oauth_access_token,
360                      :resource_owner_id => user.id,
361                      :scopes => scopes)
362       bearer_authorization_header(token.token)
363     end
364
365     def do_redact_redactable_way(headers = {})
366       way = create(:way, :with_history, :version => 4)
367       way_v3 = way.old_ways.find_by(:version => 3)
368       do_redact_way(way_v3, create(:redaction), headers)
369     end
370
371     def do_redact_way(way, redaction, headers = {})
372       get way_version_path(:id => way.way_id, :version => way.version)
373       assert_response :success, "should be able to get version #{way.version} of way #{way.way_id}."
374
375       # now redact it
376       post way_version_redact_path(:id => way.way_id, :version => way.version), :params => { :redaction => redaction.id }, :headers => headers
377     end
378
379     def propagate_tags(way, old_way)
380       way.tags.each do |k, v|
381         create(:old_way_tag, :old_way => old_way, :k => k, :v => v)
382       end
383     end
384   end
385 end