3 class OldNodesControllerTest < ActionController::TestCase
9 # test all routes which lead to this controller
12 { :path => "/api/0.6/node/1/history", :method => :get },
13 { :controller => "old_nodes", :action => "history", :id => "1" }
16 { :path => "/api/0.6/node/1/2", :method => :get },
17 { :controller => "old_nodes", :action => "version", :id => "1", :version => "2" }
20 { :path => "/api/0.6/node/1/2/redact", :method => :post },
21 { :controller => "old_nodes", :action => "redact", :id => "1", :version => "2" }
26 # test the version call by submitting several revisions of a new node
27 # to the API and ensuring that later calls to version return the
28 # matching versions of the object.
31 # FIXME: Move this test to being an integration test since it spans multiple controllers
33 private_user = create(:user, :data_public => false)
34 private_node = create(:node, :with_history, :version => 4, :changeset => create(:changeset, :user => private_user))
36 node = create(:node, :with_history, :version => 4, :changeset => create(:changeset, :user => user))
37 create_list(:node_tag, 2, :node => node)
38 # Ensure that the current tags are propagated to the history too
39 propagate_tags(node, node.old_nodes.last)
41 ## First try this with a non-public user
42 basic_authorization private_user.email, "test"
44 # setup a simple XML node
45 xml_doc = private_node.to_xml
46 xml_node = xml_doc.find("//osm/node").first
47 nodeid = private_node.id
49 # keep a hash of the versions => string, as we'll need something
50 # to test against later
53 # save a version for later checking
54 versions[xml_node["version"]] = xml_doc.to_s
56 # randomly move the node about
58 # move the node somewhere else
59 xml_node["lat"] = precision(rand * 180 - 90).to_s
60 xml_node["lon"] = precision(rand * 360 - 180).to_s
61 with_controller(NodesController.new) do
62 put :update, :params => { :id => nodeid }, :body => xml_doc.to_s
63 assert_response :forbidden, "Should have rejected node update"
64 xml_node["version"] = @response.body.to_s
66 # save a version for later checking
67 versions[xml_node["version"]] = xml_doc.to_s
70 # add a bunch of random tags
72 xml_tag = XML::Node.new("tag")
73 xml_tag["k"] = random_string
74 xml_tag["v"] = random_string
76 with_controller(NodesController.new) do
77 put :update, :params => { :id => nodeid }, :body => xml_doc.to_s
78 assert_response :forbidden,
79 "should have rejected node #{nodeid} (#{@response.body}) with forbidden"
80 xml_node["version"] = @response.body.to_s
82 # save a version for later checking
83 versions[xml_node["version"]] = xml_doc.to_s
86 # probably should check that they didn't get written to the database
88 ## Now do it with the public user
89 basic_authorization user.email, "test"
91 # setup a simple XML node
94 xml_node = xml_doc.find("//osm/node").first
97 # keep a hash of the versions => string, as we'll need something
98 # to test against later
101 # save a version for later checking
102 versions[xml_node["version"]] = xml_doc.to_s
104 # randomly move the node about
106 # move the node somewhere else
107 xml_node["lat"] = precision(rand * 180 - 90).to_s
108 xml_node["lon"] = precision(rand * 360 - 180).to_s
109 with_controller(NodesController.new) do
110 put :update, :params => { :id => nodeid }, :body => xml_doc.to_s
111 assert_response :success
112 xml_node["version"] = @response.body.to_s
114 # save a version for later checking
115 versions[xml_node["version"]] = xml_doc.to_s
118 # add a bunch of random tags
120 xml_tag = XML::Node.new("tag")
121 xml_tag["k"] = random_string
122 xml_tag["v"] = random_string
124 with_controller(NodesController.new) do
125 put :update, :params => { :id => nodeid }, :body => xml_doc.to_s
126 assert_response :success,
127 "couldn't update node #{nodeid} (#{@response.body})"
128 xml_node["version"] = @response.body.to_s
130 # save a version for later checking
131 versions[xml_node["version"]] = xml_doc.to_s
134 # check all the versions
135 versions.each_key do |key|
136 get :version, :params => { :id => nodeid, :version => key.to_i }
138 assert_response :success,
139 "couldn't get version #{key.to_i} of node #{nodeid}"
141 check_node = Node.from_xml(versions[key])
142 api_node = Node.from_xml(@response.body.to_s)
144 assert_nodes_are_equal check_node, api_node
148 def test_not_found_version
149 check_not_found_id_version(70000, 312344)
150 check_not_found_id_version(-1, -13)
151 check_not_found_id_version(create(:node).id, 24354)
152 check_not_found_id_version(24356, create(:node).version)
155 def check_not_found_id_version(id, version)
156 get :version, :params => { :id => id, :version => version }
157 assert_response :not_found
158 rescue ActionController::UrlGenerationError => ex
159 assert_match(/No route matches/, ex.to_s)
163 # Test that getting the current version is identical to picking
164 # that version with the version URI call.
165 def test_current_version
166 node = create(:node, :with_history)
167 used_node = create(:node, :with_history)
168 create(:way_node, :node => used_node)
169 node_used_by_relationship = create(:node, :with_history)
170 create(:relation_member, :member => node_used_by_relationship)
171 node_with_versions = create(:node, :with_history, :version => 4)
173 create(:node_tag, :node => node)
174 create(:node_tag, :node => used_node)
175 create(:node_tag, :node => node_used_by_relationship)
176 create(:node_tag, :node => node_with_versions)
177 propagate_tags(node, node.old_nodes.last)
178 propagate_tags(used_node, used_node.old_nodes.last)
179 propagate_tags(node_used_by_relationship, node_used_by_relationship.old_nodes.last)
180 propagate_tags(node_with_versions, node_with_versions.old_nodes.last)
182 check_current_version(node)
183 check_current_version(used_node)
184 check_current_version(node_used_by_relationship)
185 check_current_version(node_with_versions)
189 # test the redaction of an old version of a node, while not being
191 def test_redact_node_unauthorised
192 node = create(:node, :with_history, :version => 4)
193 node_v3 = node.old_nodes.find_by(:version => 3)
195 do_redact_node(node_v3,
197 assert_response :unauthorized, "should need to be authenticated to redact."
201 # test the redaction of an old version of a node, while being
202 # authorised as a normal user.
203 def test_redact_node_normal_user
204 basic_authorization create(:user).email, "test"
206 node = create(:node, :with_history, :version => 4)
207 node_v3 = node.old_nodes.find_by(:version => 3)
209 do_redact_node(node_v3,
211 assert_response :forbidden, "should need to be moderator to redact."
215 # test that, even as moderator, the current version of a node
217 def test_redact_node_current_version
218 basic_authorization create(:moderator_user).email, "test"
220 node = create(:node, :with_history, :version => 4)
221 node_v4 = node.old_nodes.find_by(:version => 4)
223 do_redact_node(node_v4,
225 assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
229 # test that redacted nodes aren't visible, regardless of
230 # authorisation except as moderator...
231 def test_version_redacted
232 node = create(:node, :with_history, :version => 2)
233 node_v1 = node.old_nodes.find_by(:version => 1)
234 node_v1.redact!(create(:redaction))
236 get :version, :params => { :id => node_v1.node_id, :version => node_v1.version }
237 assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
239 # not even to a logged-in user
240 basic_authorization create(:user).email, "test"
241 get :version, :params => { :id => node_v1.node_id, :version => node_v1.version }
242 assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
246 # test that redacted nodes aren't visible in the history
247 def test_history_redacted
248 node = create(:node, :with_history, :version => 2)
249 node_v1 = node.old_nodes.find_by(:version => 1)
250 node_v1.redact!(create(:redaction))
252 get :history, :params => { :id => node_v1.node_id }
253 assert_response :success, "Redaction shouldn't have stopped history working."
254 assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 0, "redacted node #{node_v1.node_id} version #{node_v1.version} shouldn't be present in the history."
256 # not even to a logged-in user
257 basic_authorization create(:user).email, "test"
258 get :history, :params => { :id => node_v1.node_id }
259 assert_response :success, "Redaction shouldn't have stopped history working."
260 assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 0, "redacted node #{node_v1.node_id} version #{node_v1.version} shouldn't be present in the history, even when logged in."
264 # test the redaction of an old version of a node, while being
265 # authorised as a moderator.
266 def test_redact_node_moderator
267 node = create(:node, :with_history, :version => 4)
268 node_v3 = node.old_nodes.find_by(:version => 3)
269 basic_authorization create(:moderator_user).email, "test"
271 do_redact_node(node_v3, create(:redaction))
272 assert_response :success, "should be OK to redact old version as moderator."
274 # check moderator can still see the redacted data, when passing
275 # the appropriate flag
276 get :version, :params => { :id => node_v3.node_id, :version => node_v3.version }
277 assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
278 get :version, :params => { :id => node_v3.node_id, :version => node_v3.version, :show_redactions => "true" }
279 assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
281 # and when accessed via history
282 get :history, :params => { :id => node_v3.node_id }
283 assert_response :success, "Redaction shouldn't have stopped history working."
284 assert_select "osm node[id='#{node_v3.node_id}'][version='#{node_v3.version}']", 0, "node #{node_v3.node_id} version #{node_v3.version} should not be present in the history for moderators when not passing flag."
285 get :history, :params => { :id => node_v3.node_id, :show_redactions => "true" }
286 assert_response :success, "Redaction shouldn't have stopped history working."
287 assert_select "osm node[id='#{node_v3.node_id}'][version='#{node_v3.version}']", 1, "node #{node_v3.node_id} version #{node_v3.version} should still be present in the history for moderators when passing flag."
290 # testing that if the moderator drops auth, he can't see the
291 # redacted stuff any more.
292 def test_redact_node_is_redacted
293 node = create(:node, :with_history, :version => 4)
294 node_v3 = node.old_nodes.find_by(:version => 3)
295 basic_authorization create(:moderator_user).email, "test"
297 do_redact_node(node_v3, create(:redaction))
298 assert_response :success, "should be OK to redact old version as moderator."
300 # re-auth as non-moderator
301 basic_authorization create(:user).email, "test"
303 # check can't see the redacted data
304 get :version, :params => { :id => node_v3.node_id, :version => node_v3.version }
305 assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
307 # and when accessed via history
308 get :history, :params => { :id => node_v3.node_id }
309 assert_response :success, "Redaction shouldn't have stopped history working."
310 assert_select "osm node[id='#{node_v3.node_id}'][version='#{node_v3.version}']", 0, "redacted node #{node_v3.node_id} version #{node_v3.version} shouldn't be present in the history."
314 # test the unredaction of an old version of a node, while not being
316 def test_unredact_node_unauthorised
317 node = create(:node, :with_history, :version => 2)
318 node_v1 = node.old_nodes.find_by(:version => 1)
319 node_v1.redact!(create(:redaction))
321 post :redact, :params => { :id => node_v1.node_id, :version => node_v1.version }
322 assert_response :unauthorized, "should need to be authenticated to unredact."
326 # test the unredaction of an old version of a node, while being
327 # authorised as a normal user.
328 def test_unredact_node_normal_user
330 node = create(:node, :with_history, :version => 2)
331 node_v1 = node.old_nodes.find_by(:version => 1)
332 node_v1.redact!(create(:redaction))
334 basic_authorization user.email, "test"
336 post :redact, :params => { :id => node_v1.node_id, :version => node_v1.version }
337 assert_response :forbidden, "should need to be moderator to unredact."
341 # test the unredaction of an old version of a node, while being
342 # authorised as a moderator.
343 def test_unredact_node_moderator
344 moderator_user = create(:moderator_user)
345 node = create(:node, :with_history, :version => 2)
346 node_v1 = node.old_nodes.find_by(:version => 1)
347 node_v1.redact!(create(:redaction))
349 basic_authorization moderator_user.email, "test"
351 post :redact, :params => { :id => node_v1.node_id, :version => node_v1.version }
352 assert_response :success, "should be OK to unredact old version as moderator."
354 # check moderator can now see the redacted data, when not
355 # passing the aspecial flag
356 get :version, :params => { :id => node_v1.node_id, :version => node_v1.version }
357 assert_response :success, "After unredaction, node should not be gone for moderator."
359 # and when accessed via history
360 get :history, :params => { :id => node_v1.node_id }
361 assert_response :success, "Unredaction shouldn't have stopped history working."
362 assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 1, "node #{node_v1.node_id} version #{node_v1.version} should now be present in the history for moderators without passing flag."
364 basic_authorization create(:user).email, "test"
366 # check normal user can now see the redacted data
367 get :version, :params => { :id => node_v1.node_id, :version => node_v1.version }
368 assert_response :success, "After unredaction, node should be visible to normal users."
370 # and when accessed via history
371 get :history, :params => { :id => node_v1.node_id }
372 assert_response :success, "Unredaction shouldn't have stopped history working."
373 assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 1, "node #{node_v1.node_id} version #{node_v1.version} should now be present in the history for normal users without passing flag."
378 def do_redact_node(node, redaction)
379 get :version, :params => { :id => node.node_id, :version => node.version }
380 assert_response :success, "should be able to get version #{node.version} of node #{node.node_id}."
383 post :redact, :params => { :id => node.node_id, :version => node.version, :redaction => redaction.id }
386 def check_current_version(node_id)
387 # get the current version of the node
388 current_node = with_controller(NodesController.new) do
389 get :read, :params => { :id => node_id }
390 assert_response :success, "cant get current node #{node_id}"
391 Node.from_xml(@response.body)
393 assert_not_nil current_node, "getting node #{node_id} returned nil"
395 # get the "old" version of the node from the old_node interface
396 get :version, :params => { :id => node_id, :version => current_node.version }
397 assert_response :success, "cant get old node #{node_id}, v#{current_node.version}"
398 old_node = Node.from_xml(@response.body)
400 # check the nodes are the same
401 assert_nodes_are_equal current_node, old_node
405 # returns a 16 character long string with some nasty characters in it.
406 # this ought to stress-test the tag handling as well as the versioning.
408 letters = [["!", '"', "$", "&", ";", "@"],
411 ("0".."9").to_a].flatten
412 (1..16).map { |_i| letters[rand(letters.length)] }.join
416 # truncate a floating point number to the scale that it is stored in
417 # the database. otherwise rounding errors can produce failing unit
418 # tests when they shouldn't.
420 (f * GeoRecord::SCALE).round.to_f / GeoRecord::SCALE
423 def propagate_tags(node, old_node)
424 node.tags.each do |k, v|
425 create(:old_node_tag, :old_node => old_node, :k => k, :v => v)