]> git.openstreetmap.org Git - rails.git/blob - app/controllers/api/changesets/downloads_controller.rb
Merge remote-tracking branch 'upstream/pull/5724'
[rails.git] / app / controllers / api / changesets / downloads_controller.rb
1 module Api
2   module Changesets
3     class DownloadsController < ApiController
4       before_action :setup_user_auth
5
6       authorize_resource :changeset
7
8       before_action :set_request_formats
9
10       ##
11       # download the changeset as an osmChange document.
12       #
13       # to make it easier to revert diffs it would be better if the osmChange
14       # format were reversible, i.e: contained both old and new versions of
15       # modified elements. but it doesn't at the moment...
16       #
17       # this method cannot order the database changes fully (i.e: timestamp and
18       # version number may be too coarse) so the resulting diff may not apply
19       # to a different database. however since changesets are not atomic this
20       # behaviour cannot be guaranteed anyway and is the result of a design
21       # choice.
22       def show
23         changeset = Changeset.find(params[:changeset_id])
24
25         # get all the elements in the changeset which haven't been redacted
26         # and stick them in a big array.
27         elements = if show_redactions?
28                      [changeset.old_nodes,
29                       changeset.old_ways,
30                       changeset.old_relations].flatten
31                    else
32                      [changeset.old_nodes.unredacted,
33                       changeset.old_ways.unredacted,
34                       changeset.old_relations.unredacted].flatten
35                    end
36
37         # sort the elements by timestamp and version number, as this is the
38         # almost sensible ordering available. this would be much nicer if
39         # global (SVN-style) versioning were used - then that would be
40         # unambiguous.
41         elements.sort_by! { |e| [e.timestamp, e.version] }
42
43         # generate an output element for each operation. note: we avoid looking
44         # at the history because it is simpler - but it would be more correct to
45         # check these assertions.
46         @created = []
47         @modified = []
48         @deleted = []
49
50         elements.each do |elt|
51           if elt.version == 1
52             # first version, so it must be newly-created.
53             @created << elt
54           elsif elt.visible
55             # must be a modify
56             @modified << elt
57           else
58             # if the element isn't visible then it must have been deleted
59             @deleted << elt
60           end
61         end
62
63         respond_to do |format|
64           format.xml
65         end
66       end
67
68       private
69
70       def show_redactions?
71         current_user&.moderator? && params[:show_redactions] == "true"
72       end
73     end
74   end
75 end