Split the rest action into sparate read, update and delete actions thus

allowing authorization to be done on a per-action basis without worring
about the method. This should make the user API work.

Also do a lot of cleanup of the controllers.
This commit is contained in:
Tom Hughes 2007-06-27 17:27:10 +00:00
parent 9d6ae5baae
commit dcad29dad0
17 changed files with 417 additions and 361 deletions

View file

@ -33,8 +33,6 @@ class AmfController < ApplicationController
bytes=getlong(req) # | get total size in bytes bytes=getlong(req) # | get total size in bytes
args=getvalue(req) # | get response (probably an array) args=getvalue(req) # | get response (probably an array)
RAILS_DEFAULT_LOGGER.info(" Message: #{message}")
case message case message
when 'getpresets'; results[index]=putdata(index,getpresets) when 'getpresets'; results[index]=putdata(index,getpresets)
when 'whichways'; results[index]=putdata(index,whichways(args)) when 'whichways'; results[index]=putdata(index,whichways(args))
@ -48,12 +46,10 @@ class AmfController < ApplicationController
# Write out response # Write out response
RAILS_DEFAULT_LOGGER.info(" Response: start") RAILS_DEFAULT_LOGGER.info(" Response: start")
response.headers["Content-Type"]="application/x-amf"
a,b=results.length.divmod(256) a,b=results.length.divmod(256)
render :text => proc { |response, output| render :content_type => "application/x-amf", :text => proc { |response, output|
output.write 0.chr+0.chr+0.chr+0.chr+a.chr+b.chr output.write 0.chr+0.chr+0.chr+0.chr+a.chr+b.chr
results.each do |k,v| results.each do |k,v|
RAILS_DEFAULT_LOGGER.info(" Response: encode #{k}")
output.write(v) output.write(v)
end end
} }

View file

@ -1,6 +1,5 @@
class ApiController < ApplicationController class ApiController < ApplicationController
before_filter :authorize
after_filter :compress_output after_filter :compress_output
helper :user helper :user
@ -18,7 +17,6 @@ class ApiController < ApplicationController
def trackpoints def trackpoints
@@count+=1 @@count+=1
response.headers["Content-Type"] = 'text/xml'
#retrieve the page number #retrieve the page number
page = params['page'].to_i page = params['page'].to_i
unless page unless page
@ -96,12 +94,12 @@ class ApiController < ApplicationController
#exit when we have too many requests #exit when we have too many requests
if @@count > MAX_COUNT if @@count > MAX_COUNT
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
@@count = COUNT @@count = COUNT
exit! exit!
end end
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
end end
@ -109,7 +107,6 @@ class ApiController < ApplicationController
GC.start GC.start
@@count+=1 @@count+=1
response.headers["Content-Type"] = 'text/xml'
# Figure out the bbox # Figure out the bbox
bbox = params['bbox'] bbox = params['bbox']
unless bbox and bbox.count(',') == 3 unless bbox and bbox.count(',') == 3
@ -155,7 +152,7 @@ class ApiController < ApplicationController
end end
if node_ids.length == 0 if node_ids.length == 0
render :text => "<osm version='0.4'></osm>" render :text => "<osm version='0.4'></osm>", :content_type => "text/xml"
return return
end end
@ -240,7 +237,7 @@ class ApiController < ApplicationController
doc.root << way.to_xml_node(visible_segments, user_display_name_cache) if way.visible? doc.root << way.to_xml_node(visible_segments, user_display_name_cache) if way.visible?
end end
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
#exit when we have too many requests #exit when we have too many requests
if @@count > MAX_COUNT if @@count > MAX_COUNT

View file

@ -11,7 +11,6 @@ class ApplicationController < ActionController::Base
end end
def authorize(realm='Web Password', errormessage="Couldn't authenticate you") def authorize(realm='Web Password', errormessage="Couldn't authenticate you")
unless request.get?
username, passwd = get_auth_data # parse from headers username, passwd = get_auth_data # parse from headers
# authenticate per-scheme # authenticate per-scheme
if username.nil? if username.nil?
@ -38,7 +37,6 @@ class ApplicationController < ActionController::Base
render_text(errormessage, 401) # :unauthorized render_text(errormessage, 401) # :unauthorized
end end
end end
end
# Report and error to the user # Report and error to the user
# (If anyone ever fixes Rails so it can set a http status "reason phrase", # (If anyone ever fixes Rails so it can set a http status "reason phrase",
@ -46,7 +44,7 @@ class ApplicationController < ActionController::Base
# phrase from that, we can also put the error message into the status # phrase from that, we can also put the error message into the status
# message. For now, rails won't let us) # message. For now, rails won't let us)
def report_error(message) def report_error(message)
render :nothing => true, :status => 400 render :nothing => true, :status => :bad_request
# Todo: some sort of escaping of problem characters in the message # Todo: some sort of escaping of problem characters in the message
response.headers['Error'] = message response.headers['Error'] = message
end end

View file

@ -47,9 +47,7 @@ class DiaryEntryController < ApplicationController
rss.add(latitude, longitude, entry.title, url_for({:controller => 'diary_entry', :action => 'list', :id => entry.id, :display_name => entry.user.display_name}), entry.body, entry.created_at) rss.add(latitude, longitude, entry.title, url_for({:controller => 'diary_entry', :action => 'list', :id => entry.id, :display_name => entry.user.display_name}), entry.body, entry.created_at)
end end
response.headers["Content-Type"] = 'application/rss+xml' render :text => rss.to_s, :content_type => "application/rss+xml"
render :text => rss.to_s
end end
end end

View file

@ -1,6 +1,6 @@
class MessageController < ApplicationController class MessageController < ApplicationController
layout 'site' layout 'site'
# before_filter :authorize
before_filter :authorize_web before_filter :authorize_web
before_filter :require_user before_filter :require_user

View file

@ -1,76 +1,54 @@
class NodeController < ApplicationController class NodeController < ApplicationController
require 'xml/libxml' require 'xml/libxml'
before_filter :authorize before_filter :authorize, :only => [:create, :update, :destroy]
after_filter :compress_output after_filter :compress_output
def create def create
response.headers["Content-Type"] = 'text/xml'
if request.put? if request.put?
node = Node.from_xml(request.raw_post, true) node = Node.from_xml(request.raw_post, true)
if node if node
node.user_id = @user.id node.user_id = @user.id
node.visible = 1 node.visible = true
if node.save_with_history if node.save_with_history
render :text => node.id.to_s render :text => node.id.to_s, :content_type => "text/plain"
else else
render :nothing => true, :status => 500 render :nothing => true, :status => :internal_server_error
end end
return
else else
render :nothing => true, :status => 400 # if we got here the doc didnt parse render :nothing => true, :status => :bad_request
return end
else
render :nothing => true, :status => :method_not_allowed
end end
end end
render :nothing => true, :status => 500 # something went very wrong def read
end begin
def rest
response.headers["Content-Type"] = 'text/xml'
unless Node.exists?(params[:id])
render :nothing => true, :status => 404
return
end
node = Node.find(params[:id]) node = Node.find(params[:id])
case request.method
when :get
unless node
render :nothing => true, :status => 500
return
end
unless node.visible
render :nothing => true, :status => 410
return
end
render :text => node.to_xml.to_s
return
when :delete
if node.visible if node.visible
if Segment.find(:first, :conditions => [ "visible = 1 and (node_a = ? or node_b = ?)", node.id, node.id]) render :text => node.to_xml.to_s, :content_type => "text/xml"
render :nothing => true, :status => HTTP_PRECONDITION_FAILED
else else
node.user_id = @user.id render :nothing => true, :status => :gone
node.visible = 0 end
node.save_with_history rescue ActiveRecord::RecordNotFound
render :nothing => true render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
else
render :nothing => true, :status => 410
end end
when :put def update
begin
node = Node.find(params[:id])
if node.visible
new_node = Node.from_xml(request.raw_post) new_node = Node.from_xml(request.raw_post)
if new_node if new_node and new_node.id == node.id
node.timestamp = Time.now node.timestamp = Time.now
node.user_id = @user.id node.user_id = @user.id
@ -78,31 +56,60 @@ class NodeController < ApplicationController
node.longitude = new_node.longitude node.longitude = new_node.longitude
node.tags = new_node.tags node.tags = new_node.tags
if node.id == new_node.id and node.save_with_history if node.save_with_history
render :nothing => true render :nothing => true
else else
render :nothing => true, :status => 500 render :nothing => true, :status => :internal_server_error
end end
else else
render :nothing => true, :status => 400 # if we got here the doc didnt parse render :nothing => true, :status => :bad_request
end
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
return
end end
def delete
begin
node = Node.find(params[:id])
if node.visible
if Segment.find(:first, :conditions => [ "visible = 1 and (node_a = ? or node_b = ?)", node.id, node.id])
render :nothing => true, :status => :precondition_failed
else
node.user_id = @user.id
node.visible = 0
node.save_with_history
render :nothing => true
end
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
def nodes def nodes
response.headers["Content-Type"] = 'text/xml'
ids = params['nodes'].split(',').collect { |n| n.to_i } ids = params['nodes'].split(',').collect { |n| n.to_i }
if ids.length > 0 if ids.length > 0
nodelist = Node.find(ids) doc = OSM::API.new.get_xml_doc
doc = get_xml_doc
nodelist.each do |node| Node.find(ids).each do |node|
doc.root << node.to_xml_node doc.root << node.to_xml_node
end end
render :text => doc.to_s
render :text => doc.to_s, :content_type => "text/xml"
else else
render :nothing => true, :status => 400 render :nothing => true, :status => :bad_request
end end
end end
end end

View file

@ -1,22 +1,21 @@
class OldNodeController < ApplicationController class OldNodeController < ApplicationController
require 'xml/libxml'
def history def history
response.headers["Content-Type"] = 'text/xml' begin
node = Node.find(params[:id]) node = Node.find(params[:id])
unless node
render :nothing => true, :staus => 404
return
end
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
node.old_nodes.each do |old_node| node.old_nodes.each do |old_node|
doc.root << old_node.to_xml_node doc.root << old_node.to_xml_node
end end
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
end end

View file

@ -1,20 +1,21 @@
class OldSegmentController < ApplicationController class OldSegmentController < ApplicationController
require 'xml/libxml'
def history def history
response.headers["Content-Type"] = 'text/xml' begin
segment = Segment.find(params[:id]) segment = Segment.find(params[:id])
unless segment
render :nothing => true, :staus => 404
return
end
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
segment.old_segments.each do |old_segment| segment.old_segments.each do |old_segment|
doc.root << old_segment.to_xml_node doc.root << old_segment.to_xml_node
end end
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
end end

View file

@ -1,12 +1,9 @@
class OldWayController < ApplicationController class OldWayController < ApplicationController
def history require 'xml/libxml'
response.headers["Content-Type"] = 'text/xml'
way = Way.find(params[:id])
unless way def history
render :nothing => true, :staus => 404 begin
return way = Way.find(params[:id])
end
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
@ -14,8 +11,11 @@ class OldWayController < ApplicationController
doc.root << old_way.to_xml_node doc.root << old_way.to_xml_node
end end
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
end end

View file

@ -21,8 +21,6 @@ class SearchController < ApplicationController
def do_search(do_ways,do_segments,do_nodes) def do_search(do_ways,do_segments,do_nodes)
response.headers["Content-Type"] = 'text/xml'
type = params['type'] type = params['type']
value = params['value'] value = params['value']
unless type or value unless type or value
@ -121,6 +119,6 @@ class SearchController < ApplicationController
doc.root << way.to_xml_node() doc.root << way.to_xml_node()
end end
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
end end
end end

View file

@ -1,88 +1,66 @@
class SegmentController < ApplicationController class SegmentController < ApplicationController
require 'xml/libxml' require 'xml/libxml'
before_filter :authorize before_filter :authorize, :only => [:create, :update, :destroy]
after_filter :compress_output after_filter :compress_output
def create def create
response.headers["Content-Type"] = 'text/xml'
if request.put? if request.put?
segment = Segment.from_xml(request.raw_post, true) segment = Segment.from_xml(request.raw_post, true)
if segment if segment
if segment.node_a == segment.node_b
render :nothing => true, :status => :expectation_failed
elsif !segment.preconditions_ok?
render :nothing => true, :status => :precondition_failed
else
segment.user_id = @user.id segment.user_id = @user.id
segment.from_node = Node.find(segment.node_a.to_i) segment.from_node = Node.find(segment.node_a.to_i)
segment.to_node = Node.find(segment.node_b.to_i) segment.to_node = Node.find(segment.node_b.to_i)
if segment.from_node == segment.to_node
render :nothing => true, :status => HTTP_EXPECTATION_FAILED
return
end
unless segment.preconditions_ok? # are the nodes visible?
render :nothing => true, :status => HTTP_PRECONDITION_FAILED
return
end
if segment.save_with_history if segment.save_with_history
render :text => segment.id.to_s render :text => segment.id.to_s, :content_type => "text/plain"
else else
render :nothing => true, :status => 500 render :nothing => true, :status => :internal_server_error
end
end end
return
else else
render :nothing => true, :status => 400 # if we got here the doc didnt parse render :nothing => true, :status => :bad_request
return end
else
render :nothing => true, :status => :method_not_allowed
end end
end end
render :nothing => true, :status => 500 # something went very wrong def read
end begin
def rest
response.headers["Content-Type"] = 'text/xml'
unless Segment.exists?(params[:id])
render :nothing => true, :status => 404
return
end
segment = Segment.find(params[:id]) segment = Segment.find(params[:id])
case request.method
when :get
render :text => segment.to_xml.to_s
return
when :delete
if segment.visible if segment.visible
if WaySegment.find(:first, :joins => "INNER JOIN current_ways ON current_ways.id = current_way_segments.id", :conditions => [ "current_ways.visible = 1 AND current_way_segments.segment_id = ?", segment.id ]) render :text => segment.to_xml.to_s, :content_type => "text/xml"
render :nothing => true, :status => HTTP_PRECONDITION_FAILED
else else
segment.user_id = @user.id render :nothing => true, :status => :gone
segment.visible = 0 end
segment.save_with_history rescue ActiveRecord::RecordNotFound
render :nothing => true render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
else
render :nothing => true, :status => 410
end end
when :put def update
begin
segment = Segment.find(params[:id])
if segment.visible
new_segment = Segment.from_xml(request.raw_post) new_segment = Segment.from_xml(request.raw_post)
if new_segment if new_segment and new_segment.id == segment.id
if new_segment.node_a == new_segment.node_b if new_segment.node_a == new_segment.node_b
render :nothing => true, :status => HTTP_EXPECTATION_FAILED render :nothing => true, :status => :expectation_failed
return elsif !new_segment.preconditions_ok?
end render :nothing => true, :status => :precondition_failed
else
unless new_segment.preconditions_ok? # are the nodes visible?
render :nothing => true, :status => HTTP_PRECONDITION_FAILED
return
end
segment.timestamp = Time.now segment.timestamp = Time.now
segment.user_id = @user.id segment.user_id = @user.id
segment.node_a = new_segment.node_a segment.node_a = new_segment.node_a
@ -90,46 +68,81 @@ class SegmentController < ApplicationController
segment.tags = new_segment.tags segment.tags = new_segment.tags
segment.visible = new_segment.visible segment.visible = new_segment.visible
if segment.id == new_segment.id and segment.save_with_history if segment.save_with_history
render :nothing => true render :nothing => true
else else
render :nothing => true, :status => 500 render :nothing => true, :status => :internal_server_error
end
end end
else else
render :nothing => true, :status => 400 # if we got here the doc didnt parse render :nothing => true, :status => :bad_request
end
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
end end
def delete
begin
segment = Segment.find(params[:id])
if segment.visible
if WaySegment.find(:first, :joins => "INNER JOIN current_ways ON current_ways.id = current_way_segments.id", :conditions => [ "current_ways.visible = 1 AND current_way_segments.segment_id = ?", segment.id ])
render :nothing => true, :status => :precondition_failed
else
segment.user_id = @user.id
segment.visible = 0
if segment.save_with_history
render :nothing => true
else
render :nothing => true, :status => :internal_server_error
end
end
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
def segments def segments
response.headers["Content-Type"] = 'text/xml'
ids = params['segments'].split(',').collect { |s| s.to_i } ids = params['segments'].split(',').collect { |s| s.to_i }
if ids.length > 0 if ids.length > 0
segmentlist = Segment.find(ids)
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
segmentlist.each do |segment|
Segment.find(ids).each do |segment|
doc.root << segment.to_xml_node doc.root << segment.to_xml_node
end end
render :text => doc.to_s
render :text => doc.to_s, :content_type => "text/xml"
else else
render :nothing => true, :status => 400 render :nothing => true, :status => :bad_request
end end
end end
def segments_for_node def segments_for_node
response.headers["Content-Type"] = 'text/xml'
segmentids = Segment.find(:all, :conditions => ['node_a = ? OR node_b = ?', params[:id], params[:id]]).collect { |s| s.id }.uniq segmentids = Segment.find(:all, :conditions => ['node_a = ? OR node_b = ?', params[:id], params[:id]]).collect { |s| s.id }.uniq
if segmentids.length > 0 if segmentids.length > 0
segmentlist = Segment.find(segmentids)
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
segmentlist.each do |segment|
Segment.find(segmentids).each do |segment|
doc.root << segment.to_xml_node doc.root << segment.to_xml_node
end end
render :text => doc.to_s
else
render :nothing => true, :status => 400
end
end
render :text => doc.to_s, :content_type => "text/xml"
else
render :nothing => true, :status => :bad_request
end
end
end end

View file

@ -139,8 +139,7 @@ class SwfController < ApplicationController
m=packRect(bounds_left,bounds_right,bounds_bottom,bounds_top) + 0.chr + 12.chr + packUI16(1) + m m=packRect(bounds_left,bounds_right,bounds_bottom,bounds_top) + 0.chr + 12.chr + packUI16(1) + m
m='FWS' + 6.chr + packUI32(m.length+8) + m m='FWS' + 6.chr + packUI32(m.length+8) + m
response.headers["Content-Type"]="application/x-shockwave-flash" render :text => m, :content_type => "application/x-shockwave-flash"
render :text=>m
end end
private private

View file

@ -95,7 +95,7 @@ class TraceController < ApplicationController
@trace = Trace.find(params[:id]) @trace = Trace.find(params[:id])
unless @trace.public unless @trace.public
if @user if @user
render :nothing, :status => 401 if @trace.user.id != @user.id render :nothing, :status => :forbidden if @trace.user.id != @user.id
end end
end end
end end
@ -126,7 +126,7 @@ class TraceController < ApplicationController
if trace and (trace.public? or (@user and @user == trace.user)) if trace and (trace.public? or (@user and @user == trace.user))
send_file(trace.trace_name, :filename => "#{trace.id}.gpx", :type => trace.mime_type, :disposition => 'attachment') send_file(trace.trace_name, :filename => "#{trace.id}.gpx", :type => trace.mime_type, :disposition => 'attachment')
else else
render :nothing, :status => 404 render :nothing, :status => :not_found
end end
end end
@ -150,34 +150,55 @@ class TraceController < ApplicationController
rss.add(trace.latitude, trace.longitude, trace.name, url_for({:controller => 'trace', :action => 'view', :id => trace.id, :display_name => trace.user.display_name}), "<img src='#{url_for({:controller => 'trace', :action => 'icon', :id => trace.id, :user_login => trace.user.display_name})}'> GPX file with #{trace.size} points from #{trace.user.display_name}", trace.timestamp) rss.add(trace.latitude, trace.longitude, trace.name, url_for({:controller => 'trace', :action => 'view', :id => trace.id, :display_name => trace.user.display_name}), "<img src='#{url_for({:controller => 'trace', :action => 'icon', :id => trace.id, :user_login => trace.user.display_name})}'> GPX file with #{trace.size} points from #{trace.user.display_name}", trace.timestamp)
end end
response.headers["Content-Type"] = 'application/rss+xml' render :text => rss.to_s, :content_type => "application/rss+xml"
render :text => rss.to_s
end end
def picture def picture
begin
trace = Trace.find(params[:id]) trace = Trace.find(params[:id])
if trace and (trace.public? or (@user and @user == trace.user))
if trace.public? or (@user and @user == trace.user)
send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline') send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
else else
render :nothing, :status => 404 render :nothing, :status => :forbidden
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
end end
def icon def icon
begin
trace = Trace.find(params[:id]) trace = Trace.find(params[:id])
if trace and (trace.public? or (@user and @user == trace.user))
if trace.public? or (@user and @user == trace.user)
send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline') send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
else else
render :nothing, :status => 404 render :nothing, :status => :forbidden
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
end end
def api_details def api_details
begin
trace = Trace.find(params[:id]) trace = Trace.find(params[:id])
doc = OSM::API.new.get_xml_doc
doc.root << trace.to_xml_node() if trace.public? or trace.user == @user if trace.public? or trace.user == @user
render :text => doc.to_s render :text => trace.to_xml.to_s, :content_type => "text/xml"
else
render :nothing => true, :status => :forbidden
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
def api_data def api_data
@ -205,8 +226,7 @@ class TraceController < ApplicationController
flash[:notice] = "Your GPX file has been uploaded and is awaiting insertion in to the database. This will usually happen within half an hour, and an email will be sent to you on completion." flash[:notice] = "Your GPX file has been uploaded and is awaiting insertion in to the database. This will usually happen within half an hour, and an email will be sent to you on completion."
render :nothing => true render :nothing => true
else else
render :nothing => true, :status => 400 # er FIXME what fricking code to return? render :nothing => true, :status => :internal_server_error
end end
end end
end end

View file

@ -165,7 +165,7 @@ class UserController < ApplicationController
@user.save! @user.save!
render :nothing => true render :nothing => true
else else
render :status => 400, :nothing => true render :nothing => true, :status => :method_not_allowed
end end
end end

View file

@ -1,50 +1,113 @@
class WayController < ApplicationController class WayController < ApplicationController
require 'xml/libxml' require 'xml/libxml'
before_filter :authorize before_filter :authorize, :only => [:create, :update, :destroy]
after_filter :compress_output after_filter :compress_output
def create def create
response.headers["Content-Type"] = 'text/xml'
if request.put? if request.put?
way = Way.from_xml(request.raw_post, true) way = Way.from_xml(request.raw_post, true)
if way if way
if !way.preconditions_ok?
render :nothing => true, :status => :precondition_failed
else
way.user_id = @user.id way.user_id = @user.id
unless way.preconditions_ok? # are the segments (and their nodes) visible? if way.save_with_history
render :nothing => true, :status => HTTP_PRECONDITION_FAILED render :text => way.id.to_s, :content_type => "text/plain"
return else
render :nothing => true, :status => :internal_server_error
end end
end
else
render :nothing => true, :status => :bad_request
end
else
render :nothing => true, :status => :method_not_allowed
end
end
def read
begin
way = Way.find(params[:id])
if way.visible
render :text => way.to_xml.to_s, :content_type => "text/xml"
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end
def update
begin
way = Way.find(params[:id])
if way.visible
new_way = Way.from_xml(request.raw_post)
if new_way and new_way.id == way.id
if !new_way.preconditions_ok?
render :nothing => true, :status => :precondition_failed
else
way.user_id = @user.id
way.tags = new_way.tags
way.segs = new_way.segs
way.timestamp = new_way.timestamp
way.visible = true
if way.save_with_history if way.save_with_history
render :text => way.id.to_s render :nothing => true
else else
render :nothing => true, :status => 500 render :nothing => true, :status => :internal_server_error
end
end end
return
else else
render :nothing => true, :status => 400 # if we got here the doc didnt parse render :nothing => true, :status => :bad_request
return end
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
end end
render :nothing => true, :status => 500 # something went very wrong def delete
begin
way = Way.find(params[:id])
if way.visible
way.user_id = @user.id
way.visible = false
if way.save_with_history
render :nothing => true
else
render :nothing => true, :status => :internal_server_error
end
else
render :nothing => true, :status => :gone
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end
end end
def full def full
unless Way.exists?(params[:id]) begin
render :nothing => true, :status => 404
return
end
way = Way.find(params[:id]) way = Way.find(params[:id])
unless way.visible if way.visible
render :nothing => true, :status => 410
return
end
# In future, we might want to do all the data fetch in one step # In future, we might want to do all the data fetch in one step
seg_ids = way.segs + [-1] seg_ids = way.segs + [-1]
segments = Segment.find_by_sql "select * from current_segments where visible = 1 and id IN (#{seg_ids.join(',')})" segments = Segment.find_by_sql "select * from current_segments where visible = 1 and id IN (#{seg_ids.join(',')})"
@ -64,91 +127,46 @@ class WayController < ApplicationController
end end
doc.root << way.to_xml_node() doc.root << way.to_xml_node()
render :text => doc.to_s render :text => doc.to_s, :content_type => "text/xml"
end
def rest
response.headers["Content-Type"] = 'text/xml'
unless Way.exists?(params[:id])
render :nothing => true, :status => 404
return
end
way = Way.find(params[:id])
case request.method
when :get
unless way.visible
render :nothing => true, :status => 410
return
end
render :text => way.to_xml.to_s
when :delete
if way.visible
way.user_id = @user.id
way.visible = false
way.save_with_history
render :nothing => true
else else
render :nothing => true, :status => 410 render :nothing => true, :status => :gone
end
when :put
new_way = Way.from_xml(request.raw_post)
if new_way
unless new_way.preconditions_ok? # are the segments (and their nodes) visible?
render :nothing => true, :status => HTTP_PRECONDITION_FAILED
return
end
way.user_id = @user.id
way.tags = new_way.tags
way.segs = new_way.segs
way.timestamp = new_way.timestamp
way.visible = true
if way.id == new_way.id and way.save_with_history
render :nothing => true
else
render :nothing => true, :status => 500
end
else
render :nothing => true, :status => 400 # if we got here the doc didnt parse
end end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
rescue
render :nothing => true, :status => :internal_server_error
end end
end end
def ways def ways
response.headers["Content-Type"] = 'text/xml'
ids = params['ways'].split(',').collect { |w| w.to_i } ids = params['ways'].split(',').collect { |w| w.to_i }
if ids.length > 0 if ids.length > 0
waylist = Way.find(ids)
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
waylist.each do |way|
Way.find(ids).each do |way|
doc.root << way.to_xml_node doc.root << way.to_xml_node
end end
render :text => doc.to_s
render :text => doc.to_s, :content_type => "text/xml"
else else
render :nothing => true, :status => 400 render :nothing => true, :status => :bad_request
end end
end end
def ways_for_segment def ways_for_segment
response.headers["Content-Type"] = 'text/xml'
wayids = WaySegment.find(:all, :conditions => ['segment_id = ?', params[:id]]).collect { |ws| ws.id }.uniq wayids = WaySegment.find(:all, :conditions => ['segment_id = ?', params[:id]]).collect { |ws| ws.id }.uniq
if wayids.length > 0 if wayids.length > 0
waylist = Way.find(wayids)
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
waylist.each do |way|
Way.find(wayids).each do |way|
doc.root << way.to_xml_node doc.root << way.to_xml_node
end end
render :text => doc.to_s
else
render :nothing => true, :status => 400
end
end
render :text => doc.to_s, :content_type => "text/xml"
else
render :nothing => true, :status => :bad_request
end
end
end end

View file

@ -76,6 +76,12 @@ class Trace < ActiveRecord::Base
return `file -bi #{trace_name}`.chomp return `file -bi #{trace_name}`.chomp
end end
def to_xml
doc = OSM::API.new.get_xml_doc
doc.root << to_xml_node()
return doc
end
def to_xml_node def to_xml_node
el1 = XML::Node.new 'gpx_file' el1 = XML::Node.new 'gpx_file'
el1['id'] = self.id.to_s el1['id'] = self.id.to_s

View file

@ -4,19 +4,25 @@ ActionController::Routing::Routes.draw do |map|
map.connect "api/#{API_VERSION}/node/create", :controller => 'node', :action => 'create' map.connect "api/#{API_VERSION}/node/create", :controller => 'node', :action => 'create'
map.connect "api/#{API_VERSION}/node/:id/segments", :controller => 'segment', :action => 'segments_for_node', :id => /\d+/ map.connect "api/#{API_VERSION}/node/:id/segments", :controller => 'segment', :action => 'segments_for_node', :id => /\d+/
map.connect "api/#{API_VERSION}/node/:id/history", :controller => 'old_node', :action => 'history', :id => /\d+/ map.connect "api/#{API_VERSION}/node/:id/history", :controller => 'old_node', :action => 'history', :id => /\d+/
map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'rest', :id => /\d+/ map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'read', :id => /\d+/, :conditions => { :method => :get }
map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'update', :id => /\d+/, :conditions => { :method => :put }
map.connect "api/#{API_VERSION}/node/:id", :controller => 'node', :action => 'delete', :id => /\d+/, :conditions => { :method => :delete }
map.connect "api/#{API_VERSION}/nodes", :controller => 'node', :action => 'nodes', :id => nil map.connect "api/#{API_VERSION}/nodes", :controller => 'node', :action => 'nodes', :id => nil
map.connect "api/#{API_VERSION}/segment/create", :controller => 'segment', :action => 'create' map.connect "api/#{API_VERSION}/segment/create", :controller => 'segment', :action => 'create'
map.connect "api/#{API_VERSION}/segment/:id/ways", :controller => 'way', :action => 'ways_for_segment', :id => /\d+/ map.connect "api/#{API_VERSION}/segment/:id/ways", :controller => 'way', :action => 'ways_for_segment', :id => /\d+/
map.connect "api/#{API_VERSION}/segment/:id/history", :controller => 'old_segment', :action => 'history', :id => /\d+/ map.connect "api/#{API_VERSION}/segment/:id/history", :controller => 'old_segment', :action => 'history', :id => /\d+/
map.connect "api/#{API_VERSION}/segment/:id", :controller => 'segment', :action => 'rest', :id => /\d+/ map.connect "api/#{API_VERSION}/segment/:id", :controller => 'segment', :action => 'read', :id => /\d+/, :conditions => { :method => :get }
map.connect "api/#{API_VERSION}/segment/:id", :controller => 'segment', :action => 'update', :id => /\d+/, :conditions => { :method => :put }
map.connect "api/#{API_VERSION}/segment/:id", :controller => 'segment', :action => 'delete', :id => /\d+/, :conditions => { :method => :delete }
map.connect "api/#{API_VERSION}/segments", :controller => 'segment', :action => 'segments', :id => nil map.connect "api/#{API_VERSION}/segments", :controller => 'segment', :action => 'segments', :id => nil
map.connect "api/#{API_VERSION}/way/create", :controller => 'way', :action => 'create' map.connect "api/#{API_VERSION}/way/create", :controller => 'way', :action => 'create'
map.connect "api/#{API_VERSION}/way/:id/history", :controller => 'old_way', :action => 'history', :id => /\d+/ map.connect "api/#{API_VERSION}/way/:id/history", :controller => 'old_way', :action => 'history', :id => /\d+/
map.connect "api/#{API_VERSION}/way/:id/full", :controller => 'way', :action => 'full', :id => /\d+/ map.connect "api/#{API_VERSION}/way/:id/full", :controller => 'way', :action => 'full', :id => /\d+/
map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'rest', :id => /\d+/ map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'read', :id => /\d+/, :conditions => { :method => :get }
map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'update', :id => /\d+/, :conditions => { :method => :put }
map.connect "api/#{API_VERSION}/way/:id", :controller => 'way', :action => 'delete', :id => /\d+/, :conditions => { :method => :delete }
map.connect "api/#{API_VERSION}/ways", :controller => 'way', :action => 'ways', :id => nil map.connect "api/#{API_VERSION}/ways", :controller => 'way', :action => 'ways', :id => nil
map.connect "api/#{API_VERSION}/map", :controller => 'api', :action => 'map' map.connect "api/#{API_VERSION}/map", :controller => 'api', :action => 'map'