]> git.openstreetmap.org Git - rails.git/blob - app/controllers/api/traces_controller.rb
Standardise on avoiding except lists for check_api_readable
[rails.git] / app / controllers / api / traces_controller.rb
1 module Api
2   class TracesController < ApiController
3     before_action :check_api_readable
4     before_action :check_api_writable, :only => [:create, :update, :destroy]
5     before_action :set_locale
6     before_action :authorize
7
8     authorize_resource
9
10     before_action :offline_error, :only => [:create, :destroy, :data]
11     around_action :api_call_handle_error
12
13     def show
14       @trace = Trace.visible.find(params[:id])
15
16       head :forbidden unless @trace.public? || @trace.user == current_user
17     end
18
19     def create
20       tags = params[:tags] || ""
21       description = params[:description] || ""
22       visibility = params[:visibility]
23
24       if visibility.nil?
25         visibility = if params[:public]&.to_i&.nonzero?
26                        "public"
27                      else
28                        "private"
29                      end
30       end
31
32       if params[:file].respond_to?(:read)
33         trace = do_create(params[:file], tags, description, visibility)
34
35         if trace.id
36           trace.schedule_import
37           render :plain => trace.id.to_s
38         elsif trace.valid?
39           head :internal_server_error
40         else
41           head :bad_request
42         end
43       else
44         head :bad_request
45       end
46     end
47
48     def update
49       trace = Trace.visible.find(params[:id])
50
51       if trace.user == current_user
52         trace.update_from_xml(request.raw_post)
53         trace.save!
54
55         head :ok
56       else
57         head :forbidden
58       end
59     end
60
61     def destroy
62       trace = Trace.visible.find(params[:id])
63
64       if trace.user == current_user
65         trace.visible = false
66         trace.save!
67         trace.schedule_destruction
68
69         head :ok
70       else
71         head :forbidden
72       end
73     end
74
75     def data
76       trace = Trace.visible.find(params[:id])
77
78       if trace.public? || trace.user == current_user
79         if request.format == Mime[:xml]
80           send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
81         elsif request.format == Mime[:gpx]
82           send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
83         elsif trace.file.attached?
84           redirect_to rails_blob_path(trace.file, :disposition => "attachment")
85         else
86           send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
87         end
88       else
89         head :forbidden
90       end
91     end
92
93     private
94
95     def do_create(file, tags, description, visibility)
96       # Sanitise the user's filename
97       name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, "_")
98
99       # Create the trace object, falsely marked as already
100       # inserted to stop the import daemon trying to load it
101       trace = Trace.new(
102         :name => name,
103         :tagstring => tags,
104         :description => description,
105         :visibility => visibility,
106         :inserted => false,
107         :user => current_user,
108         :timestamp => Time.now.utc,
109         :file => file
110       )
111
112       # Save the trace object
113       trace.save!
114
115       # Finally save the user's preferred privacy level
116       if pref = current_user.preferences.find_by(:k => "gps.trace.visibility")
117         pref.v = visibility
118         pref.save
119       else
120         current_user.preferences.create(:k => "gps.trace.visibility", :v => visibility)
121       end
122
123       trace
124     end
125
126     def offline_error
127       report_error "GPX files offline for maintenance", :service_unavailable if Settings.status == "gpx_offline"
128     end
129   end
130 end