openstreetmap-website/app/controllers/api/changesets/downloads_controller.rb
2025-02-23 21:03:31 +03:00

75 lines
2.5 KiB
Ruby

module Api
module Changesets
class DownloadsController < ApiController
before_action :setup_user_auth
authorize_resource :changeset
before_action :set_request_formats
##
# download the changeset as an osmChange document.
#
# to make it easier to revert diffs it would be better if the osmChange
# format were reversible, i.e: contained both old and new versions of
# modified elements. but it doesn't at the moment...
#
# this method cannot order the database changes fully (i.e: timestamp and
# version number may be too coarse) so the resulting diff may not apply
# to a different database. however since changesets are not atomic this
# behaviour cannot be guaranteed anyway and is the result of a design
# choice.
def show
changeset = Changeset.find(params[:changeset_id])
# get all the elements in the changeset which haven't been redacted
# and stick them in a big array.
elements = if show_redactions?
[changeset.old_nodes,
changeset.old_ways,
changeset.old_relations].flatten
else
[changeset.old_nodes.unredacted,
changeset.old_ways.unredacted,
changeset.old_relations.unredacted].flatten
end
# sort the elements by timestamp and version number, as this is the
# almost sensible ordering available. this would be much nicer if
# global (SVN-style) versioning were used - then that would be
# unambiguous.
elements.sort_by! { |e| [e.timestamp, e.version] }
# generate an output element for each operation. note: we avoid looking
# at the history because it is simpler - but it would be more correct to
# check these assertions.
@created = []
@modified = []
@deleted = []
elements.each do |elt|
if elt.version == 1
# first version, so it must be newly-created.
@created << elt
elsif elt.visible
# must be a modify
@modified << elt
else
# if the element isn't visible then it must have been deleted
@deleted << elt
end
end
respond_to do |format|
format.xml
end
end
private
def show_redactions?
current_user&.moderator? && params[:show_redactions] == "true"
end
end
end
end