Simplify deny_access handling
[rails.git] / app / controllers / api / tracepoints_controller.rb
1 module Api
2   class TracepointsController < ApiController
3     authorize_resource
4
5     before_action :check_api_readable
6     around_action :api_call_handle_error, :api_call_timeout
7
8     # Get an XML response containing a list of tracepoints that have been uploaded
9     # within the specified bounding box, and in the specified page.
10     def index
11       # retrieve the page number
12       page = params["page"].to_s.to_i
13
14       unless page >= 0
15         report_error("Page number must be greater than or equal to 0")
16         return
17       end
18
19       offset = page * Settings.tracepoints_per_page
20
21       # Figure out the bbox
22       # check boundary is sane and area within defined
23       # see /config/application.yml
24       begin
25         bbox = BoundingBox.from_bbox_params(params)
26         bbox.check_boundaries
27         bbox.check_size
28       rescue StandardError => err
29         report_error(err.message)
30         return
31       end
32
33       # get all the points
34       ordered_points = Tracepoint.bbox(bbox).joins(:trace).where(:gpx_files => { :visibility => %w[trackable identifiable] }).order("gpx_id DESC, trackid ASC, timestamp ASC")
35       unordered_points = Tracepoint.bbox(bbox).joins(:trace).where(:gpx_files => { :visibility => %w[public private] }).order("gps_points.latitude", "gps_points.longitude", "gps_points.timestamp")
36       points = ordered_points.union_all(unordered_points).offset(offset).limit(Settings.tracepoints_per_page)
37
38       doc = XML::Document.new
39       doc.encoding = XML::Encoding::UTF_8
40       root = XML::Node.new "gpx"
41       root["version"] = "1.0"
42       root["creator"] = "OpenStreetMap.org"
43       root["xmlns"] = "http://www.topografix.com/GPX/1/0"
44
45       doc.root = root
46
47       # initialise these variables outside of the loop so that they
48       # stay in scope and don't get free'd up by the GC during the
49       # loop.
50       gpx_id = -1
51       trackid = -1
52       track = nil
53       trkseg = nil
54       anon_track = nil
55       anon_trkseg = nil
56       gpx_file = nil
57       timestamps = false
58
59       points.each do |point|
60         if gpx_id != point.gpx_id
61           gpx_id = point.gpx_id
62           trackid = -1
63           gpx_file = Trace.find(gpx_id)
64
65           if gpx_file.trackable?
66             track = XML::Node.new "trk"
67             doc.root << track
68             timestamps = true
69
70             if gpx_file.identifiable?
71               track << (XML::Node.new("name") << gpx_file.name)
72               track << (XML::Node.new("desc") << gpx_file.description)
73               track << (XML::Node.new("url") << url_for(:controller => "/traces", :action => "show", :display_name => gpx_file.user.display_name, :id => gpx_file.id))
74             end
75           else
76             # use the anonymous track segment if the user hasn't allowed
77             # their GPX points to be tracked.
78             timestamps = false
79             if anon_track.nil?
80               anon_track = XML::Node.new "trk"
81               doc.root << anon_track
82             end
83             track = anon_track
84           end
85         end
86
87         if trackid != point.trackid
88           if gpx_file.trackable?
89             trkseg = XML::Node.new "trkseg"
90             track << trkseg
91             trackid = point.trackid
92           else
93             if anon_trkseg.nil?
94               anon_trkseg = XML::Node.new "trkseg"
95               anon_track << anon_trkseg
96             end
97             trkseg = anon_trkseg
98           end
99         end
100
101         trkseg << point.to_xml_node(timestamps)
102       end
103
104       response.headers["Content-Disposition"] = "attachment; filename=\"tracks.gpx\""
105
106       render :xml => doc.to_s
107     end
108   end
109 end