]> git.openstreetmap.org Git - rails.git/blob - test/controllers/api/old_ways_controller_test.rb
Merge remote-tracking branch 'upstream/pull/5274'
[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 => "show", :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 => "show", :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(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 = bearer_authorization_header
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 = bearer_authorization_header create(:moderator_user)
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_without_write_redactions_scope
122       auth_header = bearer_authorization_header(create(:user), :scopes => %w[read_prefs write_api])
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_redactions_scope
128       auth_header = bearer_authorization_header(create(:user), :scopes => %w[write_redactions])
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_moderator_without_write_redactions_scope
134       auth_header = bearer_authorization_header(create(:moderator_user), :scopes => %w[read_prefs write_api])
135       do_redact_redactable_way(auth_header)
136       assert_response :forbidden, "should need to have write_redactions scope to redact."
137     end
138
139     def test_redact_way_by_moderator_with_write_redactions_scope
140       auth_header = bearer_authorization_header(create(:moderator_user), :scopes => %w[write_redactions])
141       do_redact_redactable_way(auth_header)
142       assert_response :success, "should be OK to redact old version as moderator with write_redactions scope."
143     end
144
145     ##
146     # test that redacted ways aren't visible, regardless of
147     # authorisation except as moderator...
148     def test_version_redacted
149       way = create(:way, :with_history, :version => 2)
150       way_v1 = way.old_ways.find_by(:version => 1)
151       way_v1.redact!(create(:redaction))
152
153       get api_old_way_path(way_v1.way_id, way_v1.version)
154       assert_response :forbidden, "Redacted way shouldn't be visible via the version API."
155
156       # not even to a logged-in user
157       auth_header = bearer_authorization_header
158       get api_old_way_path(way_v1.way_id, way_v1.version), :headers => auth_header
159       assert_response :forbidden, "Redacted way shouldn't be visible via the version API, even when logged in."
160     end
161
162     ##
163     # test that redacted ways aren't visible in the history
164     def test_history_redacted
165       way = create(:way, :with_history, :version => 2)
166       way_v1 = way.old_ways.find_by(:version => 1)
167       way_v1.redact!(create(:redaction))
168
169       get api_way_history_path(way)
170       assert_response :success, "Redaction shouldn't have stopped history working."
171       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
172                     "redacted way #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history."
173
174       # not even to a logged-in user
175       auth_header = bearer_authorization_header
176       get api_way_history_path(way), :headers => auth_header
177       assert_response :success, "Redaction shouldn't have stopped history working."
178       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
179                     "redacted node #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history, even when logged in."
180     end
181
182     ##
183     # test the redaction of an old version of a way, while being
184     # authorised as a moderator.
185     def test_redact_way_moderator
186       way = create(:way, :with_history, :version => 4)
187       way_v3 = way.old_ways.find_by(:version => 3)
188       auth_header = bearer_authorization_header create(:moderator_user)
189
190       do_redact_way(way_v3, create(:redaction), auth_header)
191       assert_response :success, "should be OK to redact old version as moderator."
192
193       # check moderator can still see the redacted data, when passing
194       # the appropriate flag
195       get api_old_way_path(way_v3.way_id, way_v3.version), :headers => auth_header
196       assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
197       get api_old_way_path(way_v3.way_id, way_v3.version, :show_redactions => "true"), :headers => auth_header
198       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
199
200       # and when accessed via history
201       get api_way_history_path(way), :headers => auth_header
202       assert_response :success, "Redaction shouldn't have stopped history working."
203       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 0,
204                     "way #{way_v3.way_id} version #{way_v3.version} should not be present in the history for moderators when not passing flag."
205       get api_way_history_path(way, :show_redactions => "true"), :headers => auth_header
206       assert_response :success, "Redaction shouldn't have stopped history working."
207       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 1,
208                     "way #{way_v3.way_id} version #{way_v3.version} should still be present in the history for moderators when passing flag."
209     end
210
211     # testing that if the moderator drops auth, he can't see the
212     # redacted stuff any more.
213     def test_redact_way_is_redacted
214       way = create(:way, :with_history, :version => 4)
215       way_v3 = way.old_ways.find_by(:version => 3)
216       auth_header = bearer_authorization_header create(:moderator_user)
217
218       do_redact_way(way_v3, create(:redaction), auth_header)
219       assert_response :success, "should be OK to redact old version as moderator."
220
221       # re-auth as non-moderator
222       auth_header = bearer_authorization_header
223
224       # check can't see the redacted data
225       get api_old_way_path(way_v3.way_id, way_v3.version), :headers => auth_header
226       assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
227
228       # and when accessed via history
229       get api_way_history_path(way), :headers => auth_header
230       assert_response :success, "Redaction shouldn't have stopped history working."
231       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 0,
232                     "redacted way #{way_v3.way_id} version #{way_v3.version} shouldn't be present in the history."
233     end
234
235     ##
236     # test the unredaction of an old version of a way, while not being
237     # authorised.
238     def test_unredact_way_unauthorised
239       way = create(:way, :with_history, :version => 2)
240       way_v1 = way.old_ways.find_by(:version => 1)
241       way_v1.redact!(create(:redaction))
242
243       post way_version_redact_path(way_v1.way_id, way_v1.version)
244       assert_response :unauthorized, "should need to be authenticated to unredact."
245     end
246
247     ##
248     # test the unredaction of an old version of a way, while being
249     # authorised as a normal user.
250     def test_unredact_way_normal_user
251       way = create(:way, :with_history, :version => 2)
252       way_v1 = way.old_ways.find_by(:version => 1)
253       way_v1.redact!(create(:redaction))
254
255       auth_header = bearer_authorization_header
256
257       post way_version_redact_path(way_v1.way_id, way_v1.version), :headers => auth_header
258       assert_response :forbidden, "should need to be moderator to unredact."
259     end
260
261     ##
262     # test the unredaction of an old version of a way, while being
263     # authorised as a moderator.
264     def test_unredact_way_moderator
265       moderator_user = create(:moderator_user)
266       way = create(:way, :with_history, :version => 2)
267       way_v1 = way.old_ways.find_by(:version => 1)
268       way_v1.redact!(create(:redaction))
269
270       auth_header = bearer_authorization_header moderator_user
271
272       post way_version_redact_path(way_v1.way_id, way_v1.version), :headers => auth_header
273       assert_response :success, "should be OK to unredact old version as moderator."
274
275       # check moderator can still see the unredacted data, without passing
276       # the appropriate flag
277       get api_old_way_path(way_v1.way_id, way_v1.version), :headers => auth_header
278       assert_response :success, "After unredaction, node should not be gone for moderator."
279
280       # and when accessed via history
281       get api_way_history_path(way), :headers => auth_header
282       assert_response :success, "Unredaction shouldn't have stopped history working."
283       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 1,
284                     "way #{way_v1.way_id} version #{way_v1.version} should still be present in the history for moderators."
285
286       auth_header = bearer_authorization_header
287
288       # check normal user can now see the unredacted data
289       get api_old_way_path(way_v1.way_id, way_v1.version), :headers => auth_header
290       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
291
292       # and when accessed via history
293       get api_way_history_path(way), :headers => auth_header
294       assert_response :success, "Redaction shouldn't have stopped history working."
295       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 1,
296                     "way #{way_v1.way_id} version #{way_v1.version} should still be present in the history for normal users."
297     end
298
299     private
300
301     ##
302     # check that the current version of a way is equivalent to the
303     # version which we're getting from the versions call.
304     def check_current_version(way_id)
305       # get the current version
306       current_way = with_controller(WaysController.new) do
307         get api_way_path(way_id)
308         assert_response :success, "can't get current way #{way_id}"
309         Way.from_xml(@response.body)
310       end
311       assert_not_nil current_way, "getting way #{way_id} returned nil"
312
313       # get the "old" version of the way from the version method
314       get api_old_way_path(way_id, current_way.version)
315       assert_response :success, "can't get old way #{way_id}, v#{current_way.version}"
316       old_way = Way.from_xml(@response.body)
317
318       # check that the ways are identical
319       assert_ways_are_equal current_way, old_way
320     end
321
322     ##
323     # look at all the versions of the way in the history and get each version from
324     # the versions call. check that they're the same.
325     def check_history_equals_versions(way_id)
326       get api_way_history_path(way_id)
327       assert_response :success, "can't get way #{way_id} from API"
328       history_doc = XML::Parser.string(@response.body).parse
329       assert_not_nil history_doc, "parsing way #{way_id} history failed"
330
331       history_doc.find("//osm/way").each do |way_doc|
332         history_way = Way.from_xml_node(way_doc)
333         assert_not_nil history_way, "parsing way #{way_id} version failed"
334
335         get api_old_way_path(way_id, history_way.version)
336         assert_response :success, "couldn't get way #{way_id}, v#{history_way.version}"
337         version_way = Way.from_xml(@response.body)
338         assert_not_nil version_way, "failed to parse #{way_id}, v#{history_way.version}"
339
340         assert_ways_are_equal history_way, version_way
341       end
342     end
343
344     def do_redact_redactable_way(headers = {})
345       way = create(:way, :with_history, :version => 4)
346       way_v3 = way.old_ways.find_by(:version => 3)
347       do_redact_way(way_v3, create(:redaction), headers)
348     end
349
350     def do_redact_way(way, redaction, headers = {})
351       get api_old_way_path(way.way_id, way.version)
352       assert_response :success, "should be able to get version #{way.version} of way #{way.way_id}."
353
354       # now redact it
355       post way_version_redact_path(way.way_id, way.version), :params => { :redaction => redaction.id }, :headers => headers
356     end
357
358     def propagate_tags(way, old_way)
359       way.tags.each do |k, v|
360         create(:old_way_tag, :old_way => old_way, :k => k, :v => v)
361       end
362     end
363   end
364 end