Merge remote-tracking branch 'upstream/pull/2167'
[rails.git] / test / controllers / api / old_relations_controller_test.rb
1 require "test_helper"
2
3 module Api
4   class OldRelationsControllerTest < ActionController::TestCase
5     ##
6     # test all routes which lead to this controller
7     def test_routes
8       assert_routing(
9         { :path => "/api/0.6/relation/1/history", :method => :get },
10         { :controller => "api/old_relations", :action => "history", :id => "1" }
11       )
12       assert_routing(
13         { :path => "/api/0.6/relation/1/2", :method => :get },
14         { :controller => "api/old_relations", :action => "version", :id => "1", :version => "2" }
15       )
16       assert_routing(
17         { :path => "/api/0.6/relation/1/2/redact", :method => :post },
18         { :controller => "api/old_relations", :action => "redact", :id => "1", :version => "2" }
19       )
20     end
21
22     # -------------------------------------
23     # Test reading old relations.
24     # -------------------------------------
25     def test_history
26       # check that a visible relations is returned properly
27       get :history, :params => { :id => create(:relation, :with_history).id }
28       assert_response :success
29
30       # check chat a non-existent relations is not returned
31       get :history, :params => { :id => 0 }
32       assert_response :not_found
33     end
34
35     ##
36     # test the redaction of an old version of a relation, while not being
37     # authorised.
38     def test_redact_relation_unauthorised
39       relation = create(:relation, :with_history, :version => 4)
40       relation_v3 = relation.old_relations.find_by(:version => 3)
41
42       do_redact_relation(relation_v3, create(:redaction))
43       assert_response :unauthorized, "should need to be authenticated to redact."
44     end
45
46     ##
47     # test the redaction of an old version of a relation, while being
48     # authorised as a normal user.
49     def test_redact_relation_normal_user
50       relation = create(:relation, :with_history, :version => 4)
51       relation_v3 = relation.old_relations.find_by(:version => 3)
52
53       basic_authorization create(:user).email, "test"
54
55       do_redact_relation(relation_v3, create(:redaction))
56       assert_response :forbidden, "should need to be moderator to redact."
57     end
58
59     ##
60     # test that, even as moderator, the current version of a relation
61     # can't be redacted.
62     def test_redact_relation_current_version
63       relation = create(:relation, :with_history, :version => 4)
64       relation_latest = relation.old_relations.last
65
66       basic_authorization create(:moderator_user).email, "test"
67
68       do_redact_relation(relation_latest, create(:redaction))
69       assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
70     end
71
72     ##
73     # test that redacted relations aren't visible, regardless of
74     # authorisation except as moderator...
75     def test_version_redacted
76       relation = create(:relation, :with_history, :version => 2)
77       relation_v1 = relation.old_relations.find_by(:version => 1)
78       relation_v1.redact!(create(:redaction))
79
80       get :version, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
81       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
82
83       # not even to a logged-in user
84       basic_authorization create(:user).email, "test"
85       get :version, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
86       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API, even when logged in."
87     end
88
89     ##
90     # test that redacted relations aren't visible in the history
91     def test_history_redacted
92       relation = create(:relation, :with_history, :version => 2)
93       relation_v1 = relation.old_relations.find_by(:version => 1)
94       relation_v1.redact!(create(:redaction))
95
96       get :history, :params => { :id => relation_v1.relation_id }
97       assert_response :success, "Redaction shouldn't have stopped history working."
98       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0, "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history."
99
100       # not even to a logged-in user
101       basic_authorization create(:user).email, "test"
102       get :version, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
103       get :history, :params => { :id => relation_v1.relation_id }
104       assert_response :success, "Redaction shouldn't have stopped history working."
105       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0, "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history, even when logged in."
106     end
107
108     ##
109     # test the redaction of an old version of a relation, while being
110     # authorised as a moderator.
111     def test_redact_relation_moderator
112       relation = create(:relation, :with_history, :version => 4)
113       relation_v3 = relation.old_relations.find_by(:version => 3)
114
115       basic_authorization create(:moderator_user).email, "test"
116
117       do_redact_relation(relation_v3, create(:redaction))
118       assert_response :success, "should be OK to redact old version as moderator."
119
120       # check moderator can still see the redacted data, when passing
121       # the appropriate flag
122       get :version, :params => { :id => relation_v3.relation_id, :version => relation_v3.version }
123       assert_response :forbidden, "After redaction, relation should be gone for moderator, when flag not passed."
124       get :version, :params => { :id => relation_v3.relation_id, :version => relation_v3.version, :show_redactions => "true" }
125       assert_response :success, "After redaction, relation should not be gone for moderator, when flag passed."
126
127       # and when accessed via history
128       get :history, :params => { :id => relation_v3.relation_id }
129       assert_response :success, "Redaction shouldn't have stopped history working."
130       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 0, "relation #{relation_v3.relation_id} version #{relation_v3.version} should not be present in the history for moderators when not passing flag."
131       get :history, :params => { :id => relation_v3.relation_id, :show_redactions => "true" }
132       assert_response :success, "Redaction shouldn't have stopped history working."
133       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 1, "relation #{relation_v3.relation_id} version #{relation_v3.version} should still be present in the history for moderators when passing flag."
134     end
135
136     # testing that if the moderator drops auth, he can't see the
137     # redacted stuff any more.
138     def test_redact_relation_is_redacted
139       relation = create(:relation, :with_history, :version => 4)
140       relation_v3 = relation.old_relations.find_by(:version => 3)
141
142       basic_authorization create(:moderator_user).email, "test"
143
144       do_redact_relation(relation_v3, create(:redaction))
145       assert_response :success, "should be OK to redact old version as moderator."
146
147       # re-auth as non-moderator
148       basic_authorization create(:user).email, "test"
149
150       # check can't see the redacted data
151       get :version, :params => { :id => relation_v3.relation_id, :version => relation_v3.version }
152       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
153
154       # and when accessed via history
155       get :history, :params => { :id => relation_v3.relation_id }
156       assert_response :success, "Redaction shouldn't have stopped history working."
157       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 0, "redacted relation #{relation_v3.relation_id} version #{relation_v3.version} shouldn't be present in the history."
158     end
159
160     ##
161     # test the unredaction of an old version of a relation, while not being
162     # authorised.
163     def test_unredact_relation_unauthorised
164       relation = create(:relation, :with_history, :version => 2)
165       relation_v1 = relation.old_relations.find_by(:version => 1)
166       relation_v1.redact!(create(:redaction))
167
168       post :redact, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
169       assert_response :unauthorized, "should need to be authenticated to unredact."
170     end
171
172     ##
173     # test the unredaction of an old version of a relation, while being
174     # authorised as a normal user.
175     def test_unredact_relation_normal_user
176       relation = create(:relation, :with_history, :version => 2)
177       relation_v1 = relation.old_relations.find_by(:version => 1)
178       relation_v1.redact!(create(:redaction))
179
180       basic_authorization create(:user).email, "test"
181
182       post :redact, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
183       assert_response :forbidden, "should need to be moderator to unredact."
184     end
185
186     ##
187     # test the unredaction of an old version of a relation, while being
188     # authorised as a moderator.
189     def test_unredact_relation_moderator
190       relation = create(:relation, :with_history, :version => 2)
191       relation_v1 = relation.old_relations.find_by(:version => 1)
192       relation_v1.redact!(create(:redaction))
193
194       basic_authorization create(:moderator_user).email, "test"
195
196       post :redact, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
197       assert_response :success, "should be OK to unredact old version as moderator."
198
199       # check moderator can still see the redacted data, without passing
200       # the appropriate flag
201       get :version, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
202       assert_response :success, "After unredaction, relation should not be gone for moderator."
203
204       # and when accessed via history
205       get :history, :params => { :id => relation_v1.relation_id }
206       assert_response :success, "Redaction shouldn't have stopped history working."
207       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 1, "relation #{relation_v1.relation_id} version #{relation_v1.version} should still be present in the history for moderators."
208
209       basic_authorization create(:user).email, "test"
210
211       # check normal user can now see the redacted data
212       get :version, :params => { :id => relation_v1.relation_id, :version => relation_v1.version }
213       assert_response :success, "After redaction, node should not be gone for normal user."
214
215       # and when accessed via history
216       get :history, :params => { :id => relation_v1.relation_id }
217       assert_response :success, "Redaction shouldn't have stopped history working."
218       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 1, "relation #{relation_v1.relation_id} version #{relation_v1.version} should still be present in the history for normal users."
219     end
220
221     private
222
223     ##
224     # check that the current version of a relation is equivalent to the
225     # version which we're getting from the versions call.
226     def check_current_version(relation_id)
227       # get the current version
228       current_relation = with_controller(RelationsController.new) do
229         get :show, :params => { :id => relation_id }
230         assert_response :success, "can't get current relation #{relation_id}"
231         Relation.from_xml(@response.body)
232       end
233       assert_not_nil current_relation, "getting relation #{relation_id} returned nil"
234
235       # get the "old" version of the relation from the version method
236       get :version, :params => { :id => relation_id, :version => current_relation.version }
237       assert_response :success, "can't get old relation #{relation_id}, v#{current_relation.version}"
238       old_relation = Relation.from_xml(@response.body)
239
240       # check that the relations are identical
241       assert_relations_are_equal current_relation, old_relation
242     end
243
244     ##
245     # look at all the versions of the relation in the history and get each version from
246     # the versions call. check that they're the same.
247     def check_history_equals_versions(relation_id)
248       get :history, :params => { :id => relation_id }
249       assert_response :success, "can't get relation #{relation_id} from API"
250       history_doc = XML::Parser.string(@response.body).parse
251       assert_not_nil history_doc, "parsing relation #{relation_id} history failed"
252
253       history_doc.find("//osm/relation").each do |relation_doc|
254         history_relation = Relation.from_xml_node(relation_doc)
255         assert_not_nil history_relation, "parsing relation #{relation_id} version failed"
256
257         get :version, :params => { :id => relation_id, :version => history_relation.version }
258         assert_response :success, "couldn't get relation #{relation_id}, v#{history_relation.version}"
259         version_relation = Relation.from_xml(@response.body)
260         assert_not_nil version_relation, "failed to parse #{relation_id}, v#{history_relation.version}"
261
262         assert_relations_are_equal history_relation, version_relation
263       end
264     end
265
266     def do_redact_relation(relation, redaction)
267       get :version, :params => { :id => relation.relation_id, :version => relation.version }
268       assert_response :success, "should be able to get version #{relation.version} of relation #{relation.relation_id}."
269
270       # now redact it
271       post :redact, :params => { :id => relation.relation_id, :version => relation.version, :redaction => redaction.id }
272     end
273   end
274 end