]> git.openstreetmap.org Git - rails.git/blob - test/controllers/api/old_relations_controller_test.rb
Merge remote-tracking branch 'upstream/pull/5638'
[rails.git] / test / controllers / api / old_relations_controller_test.rb
1 require "test_helper"
2
3 module Api
4   class OldRelationsControllerTest < ActionDispatch::IntegrationTest
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 => "index", :relation_id => "1" }
11       )
12       assert_routing(
13         { :path => "/api/0.6/relation/1/history.json", :method => :get },
14         { :controller => "api/old_relations", :action => "index", :relation_id => "1", :format => "json" }
15       )
16       assert_routing(
17         { :path => "/api/0.6/relation/1/2", :method => :get },
18         { :controller => "api/old_relations", :action => "show", :id => "1", :version => "2" }
19       )
20       assert_routing(
21         { :path => "/api/0.6/relation/1/2.json", :method => :get },
22         { :controller => "api/old_relations", :action => "show", :id => "1", :version => "2", :format => "json" }
23       )
24       assert_routing(
25         { :path => "/api/0.6/relation/1/2/redact", :method => :post },
26         { :controller => "api/old_relations", :action => "redact", :id => "1", :version => "2" }
27       )
28     end
29
30     ##
31     # check that a visible relations is returned properly
32     def test_index
33       relation = create(:relation, :with_history, :version => 2)
34
35       get api_relation_versions_path(relation)
36
37       assert_response :success
38       assert_dom "osm:root", 1 do
39         assert_dom "> relation", 2 do |dom_relations|
40           assert_dom dom_relations[0], "> @id", relation.id.to_s
41           assert_dom dom_relations[0], "> @version", "1"
42
43           assert_dom dom_relations[1], "> @id", relation.id.to_s
44           assert_dom dom_relations[1], "> @version", "2"
45         end
46       end
47     end
48
49     ##
50     # check that a non-existent relations is not returned
51     def test_index_invalid
52       get api_relation_versions_path(0)
53       assert_response :not_found
54     end
55
56     ##
57     # test that redacted relations aren't visible in the history
58     def test_index_redacted
59       relation = create(:relation, :with_history, :version => 2)
60       relation_v1 = relation.old_relations.find_by(:version => 1)
61       relation_v1.redact!(create(:redaction))
62
63       get api_relation_versions_path(relation)
64       assert_response :success, "Redaction shouldn't have stopped history working."
65       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0,
66                     "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history."
67
68       # not even to a logged-in user
69       auth_header = bearer_authorization_header
70       get api_relation_versions_path(relation), :headers => auth_header
71       assert_response :success, "Redaction shouldn't have stopped history working."
72       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0,
73                     "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history, even when logged in."
74     end
75
76     ##
77     # test the redaction of an old version of a relation, while not being
78     # authorised.
79     def test_redact_relation_unauthorised
80       relation = create(:relation, :with_history, :version => 4)
81       relation_v3 = relation.old_relations.find_by(:version => 3)
82
83       do_redact_relation(relation_v3, create(:redaction))
84       assert_response :unauthorized, "should need to be authenticated to redact."
85     end
86
87     ##
88     # test the redaction of an old version of a relation, while being
89     # authorised as a normal user.
90     def test_redact_relation_normal_user
91       relation = create(:relation, :with_history, :version => 4)
92       relation_v3 = relation.old_relations.find_by(:version => 3)
93
94       auth_header = bearer_authorization_header
95
96       do_redact_relation(relation_v3, create(:redaction), auth_header)
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 relation
102     # can't be redacted.
103     def test_redact_relation_current_version
104       relation = create(:relation, :with_history, :version => 4)
105       relation_latest = relation.old_relations.last
106
107       auth_header = bearer_authorization_header create(:moderator_user)
108
109       do_redact_relation(relation_latest, create(:redaction), auth_header)
110       assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
111     end
112
113     def test_redact_relation_by_regular_without_write_redactions_scope
114       auth_header = bearer_authorization_header(create(:user), :scopes => %w[read_prefs write_api])
115       do_redact_redactable_relation(auth_header)
116       assert_response :forbidden, "should need to be moderator to redact."
117     end
118
119     def test_redact_relation_by_regular_with_write_redactions_scope
120       auth_header = bearer_authorization_header(create(:user), :scopes => %w[write_redactions])
121       do_redact_redactable_relation(auth_header)
122       assert_response :forbidden, "should need to be moderator to redact."
123     end
124
125     def test_redact_relation_by_moderator_without_write_redactions_scope
126       auth_header = bearer_authorization_header(create(:moderator_user), :scopes => %w[read_prefs write_api])
127       do_redact_redactable_relation(auth_header)
128       assert_response :forbidden, "should need to have write_redactions scope to redact."
129     end
130
131     def test_redact_relation_by_moderator_with_write_redactions_scope
132       auth_header = bearer_authorization_header(create(:moderator_user), :scopes => %w[write_redactions])
133       do_redact_redactable_relation(auth_header)
134       assert_response :success, "should be OK to redact old version as moderator with write_redactions scope."
135     end
136
137     ##
138     # test that redacted relations aren't visible, regardless of
139     # authorisation except as moderator...
140     def test_version_redacted
141       relation = create(:relation, :with_history, :version => 2)
142       relation_v1 = relation.old_relations.find_by(:version => 1)
143       relation_v1.redact!(create(:redaction))
144
145       get api_old_relation_path(relation_v1.relation_id, relation_v1.version)
146       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
147
148       # not even to a logged-in user
149       auth_header = bearer_authorization_header
150       get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
151       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API, even when logged in."
152     end
153
154     ##
155     # test the redaction of an old version of a relation, while being
156     # authorised as a moderator.
157     def test_redact_relation_moderator
158       relation = create(:relation, :with_history, :version => 4)
159       relation_v3 = relation.old_relations.find_by(:version => 3)
160
161       auth_header = bearer_authorization_header create(:moderator_user)
162
163       do_redact_relation(relation_v3, create(:redaction), auth_header)
164       assert_response :success, "should be OK to redact old version as moderator."
165
166       # check moderator can still see the redacted data, when passing
167       # the appropriate flag
168       get api_old_relation_path(relation_v3.relation_id, relation_v3.version), :headers => auth_header
169       assert_response :forbidden, "After redaction, relation should be gone for moderator, when flag not passed."
170       get api_old_relation_path(relation_v3.relation_id, relation_v3.version, :show_redactions => "true"), :headers => auth_header
171       assert_response :success, "After redaction, relation should not be gone for moderator, when flag passed."
172
173       # and when accessed via history
174       get api_relation_versions_path(relation), :headers => auth_header
175       assert_response :success, "Redaction shouldn't have stopped history working."
176       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 0,
177                     "relation #{relation_v3.relation_id} version #{relation_v3.version} should not be present in the history for moderators when not passing flag."
178       get api_relation_versions_path(relation, :show_redactions => "true"), :headers => auth_header
179       assert_response :success, "Redaction shouldn't have stopped history working."
180       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 1,
181                     "relation #{relation_v3.relation_id} version #{relation_v3.version} should still be present in the history for moderators when passing flag."
182     end
183
184     # testing that if the moderator drops auth, he can't see the
185     # redacted stuff any more.
186     def test_redact_relation_is_redacted
187       relation = create(:relation, :with_history, :version => 4)
188       relation_v3 = relation.old_relations.find_by(:version => 3)
189
190       auth_header = bearer_authorization_header create(:moderator_user)
191
192       do_redact_relation(relation_v3, create(:redaction), auth_header)
193       assert_response :success, "should be OK to redact old version as moderator."
194
195       # re-auth as non-moderator
196       auth_header = bearer_authorization_header
197
198       # check can't see the redacted data
199       get api_old_relation_path(relation_v3.relation_id, relation_v3.version), :headers => auth_header
200       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
201
202       # and when accessed via history
203       get api_relation_versions_path(relation), :headers => auth_header
204       assert_response :success, "Redaction shouldn't have stopped history working."
205       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 0,
206                     "redacted relation #{relation_v3.relation_id} version #{relation_v3.version} shouldn't be present in the history."
207     end
208
209     ##
210     # test the unredaction of an old version of a relation, while not being
211     # authorised.
212     def test_unredact_relation_unauthorised
213       relation = create(:relation, :with_history, :version => 2)
214       relation_v1 = relation.old_relations.find_by(:version => 1)
215       relation_v1.redact!(create(:redaction))
216
217       post relation_version_redact_path(relation_v1.relation_id, relation_v1.version)
218       assert_response :unauthorized, "should need to be authenticated to unredact."
219     end
220
221     ##
222     # test the unredaction of an old version of a relation, while being
223     # authorised as a normal user.
224     def test_unredact_relation_normal_user
225       relation = create(:relation, :with_history, :version => 2)
226       relation_v1 = relation.old_relations.find_by(:version => 1)
227       relation_v1.redact!(create(:redaction))
228
229       auth_header = bearer_authorization_header
230
231       post relation_version_redact_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
232       assert_response :forbidden, "should need to be moderator to unredact."
233     end
234
235     ##
236     # test the unredaction of an old version of a relation, while being
237     # authorised as a moderator.
238     def test_unredact_relation_moderator
239       relation = create(:relation, :with_history, :version => 2)
240       relation_v1 = relation.old_relations.find_by(:version => 1)
241       relation_v1.redact!(create(:redaction))
242
243       auth_header = bearer_authorization_header create(:moderator_user)
244
245       post relation_version_redact_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
246       assert_response :success, "should be OK to unredact old version as moderator."
247
248       # check moderator can still see the redacted data, without passing
249       # the appropriate flag
250       get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
251       assert_response :success, "After unredaction, relation should not be gone for moderator."
252
253       # and when accessed via history
254       get api_relation_versions_path(relation), :headers => auth_header
255       assert_response :success, "Redaction shouldn't have stopped history working."
256       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 1,
257                     "relation #{relation_v1.relation_id} version #{relation_v1.version} should still be present in the history for moderators."
258
259       auth_header = bearer_authorization_header
260
261       # check normal user can now see the redacted data
262       get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
263       assert_response :success, "After redaction, node should not be gone for normal user."
264
265       # and when accessed via history
266       get api_relation_versions_path(relation), :headers => auth_header
267       assert_response :success, "Redaction shouldn't have stopped history working."
268       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 1,
269                     "relation #{relation_v1.relation_id} version #{relation_v1.version} should still be present in the history for normal users."
270     end
271
272     private
273
274     ##
275     # check that the current version of a relation is equivalent to the
276     # version which we're getting from the versions call.
277     def check_current_version(relation_id)
278       # get the current version
279       current_relation = with_controller(RelationsController.new) do
280         get :show, :params => { :id => relation_id }
281         assert_response :success, "can't get current relation #{relation_id}"
282         Relation.from_xml(@response.body)
283       end
284       assert_not_nil current_relation, "getting relation #{relation_id} returned nil"
285
286       # get the "old" version of the relation from the version method
287       get :version, :params => { :id => relation_id, :version => current_relation.version }
288       assert_response :success, "can't get old relation #{relation_id}, v#{current_relation.version}"
289       old_relation = Relation.from_xml(@response.body)
290
291       # check that the relations are identical
292       assert_relations_are_equal current_relation, old_relation
293     end
294
295     ##
296     # look at all the versions of the relation in the history and get each version from
297     # the versions call. check that they're the same.
298     def check_history_equals_versions(relation_id)
299       get :history, :params => { :id => relation_id }
300       assert_response :success, "can't get relation #{relation_id} from API"
301       history_doc = XML::Parser.string(@response.body).parse
302       assert_not_nil history_doc, "parsing relation #{relation_id} history failed"
303
304       history_doc.find("//osm/relation").each do |relation_doc|
305         history_relation = Relation.from_xml_node(relation_doc)
306         assert_not_nil history_relation, "parsing relation #{relation_id} version failed"
307
308         get :version, :params => { :id => relation_id, :version => history_relation.version }
309         assert_response :success, "couldn't get relation #{relation_id}, v#{history_relation.version}"
310         version_relation = Relation.from_xml(@response.body)
311         assert_not_nil version_relation, "failed to parse #{relation_id}, v#{history_relation.version}"
312
313         assert_relations_are_equal history_relation, version_relation
314       end
315     end
316
317     def do_redact_redactable_relation(headers = {})
318       relation = create(:relation, :with_history, :version => 4)
319       relation_v3 = relation.old_relations.find_by(:version => 3)
320       do_redact_relation(relation_v3, create(:redaction), headers)
321     end
322
323     def do_redact_relation(relation, redaction, headers = {})
324       get api_old_relation_path(relation.relation_id, relation.version)
325       assert_response :success, "should be able to get version #{relation.version} of relation #{relation.relation_id}."
326
327       # now redact it
328       post relation_version_redact_path(relation.relation_id, relation.version), :params => { :redaction => redaction.id }, :headers => headers
329     end
330   end
331 end