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