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