Merge api06 branch to trunk.
This commit is contained in:
commit
fd6f00b069
196 changed files with 10115 additions and 1794 deletions
File diff suppressed because it is too large
Load diff
|
@ -11,12 +11,13 @@ class ApiController < ApplicationController
|
|||
@@count = COUNT
|
||||
|
||||
# The maximum area you're allowed to request, in square degrees
|
||||
MAX_REQUEST_AREA = 0.25
|
||||
MAX_REQUEST_AREA = APP_CONFIG['max_request_area']
|
||||
|
||||
# Number of GPS trace/trackpoints returned per-page
|
||||
TRACEPOINTS_PER_PAGE = 5000
|
||||
TRACEPOINTS_PER_PAGE = APP_CONFIG['tracepoints_per_page']
|
||||
|
||||
|
||||
# Get an XML response containing a list of tracepoints that have been uploaded
|
||||
# within the specified bounding box, and in the specified page.
|
||||
def trackpoints
|
||||
@@count+=1
|
||||
#retrieve the page number
|
||||
|
@ -84,6 +85,15 @@ class ApiController < ApplicationController
|
|||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
end
|
||||
|
||||
# This is probably the most common call of all. It is used for getting the
|
||||
# OSM data for a specified bounding box, usually for editing. First the
|
||||
# bounding box (bbox) is checked to make sure that it is sane. All nodes
|
||||
# are searched, then all the ways that reference those nodes are found.
|
||||
# All Nodes that are referenced by those ways are fetched and added to the list
|
||||
# of nodes.
|
||||
# Then all the relations that reference the already found nodes and ways are
|
||||
# fetched. All the nodes and ways that are referenced by those ways are then
|
||||
# fetched. Finally all the xml is returned.
|
||||
def map
|
||||
GC.start
|
||||
@@count+=1
|
||||
|
@ -109,18 +119,19 @@ class ApiController < ApplicationController
|
|||
return
|
||||
end
|
||||
|
||||
@nodes = Node.find_by_area(min_lat, min_lon, max_lat, max_lon, :conditions => "visible = 1", :limit => APP_CONFIG['max_number_of_nodes']+1)
|
||||
# FIXME um why is this area using a different order for the lat/lon from above???
|
||||
@nodes = Node.find_by_area(min_lat, min_lon, max_lat, max_lon, :conditions => {:visible => true}, :limit => APP_CONFIG['max_number_of_nodes']+1)
|
||||
# get all the nodes, by tag not yet working, waiting for change from NickB
|
||||
# need to be @nodes (instance var) so tests in /spec can be performed
|
||||
#@nodes = Node.search(bbox, params[:tag])
|
||||
|
||||
node_ids = @nodes.collect(&:id)
|
||||
if node_ids.length > APP_CONFIG['max_number_of_nodes']
|
||||
report_error("You requested too many nodes (limit is 50,000). Either request a smaller area, or use planet.osm")
|
||||
report_error("You requested too many nodes (limit is #{APP_CONFIG['max_number_of_nodes']}). Either request a smaller area, or use planet.osm")
|
||||
return
|
||||
end
|
||||
if node_ids.length == 0
|
||||
render :text => "<osm version='0.5'></osm>", :content_type => "text/xml"
|
||||
render :text => "<osm version='#{API_VERSION}' generator='#{GENERATOR}'></osm>", :content_type => "text/xml"
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -176,15 +187,15 @@ class ApiController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
relations = Relation.find_for_nodes(visible_nodes.keys, :conditions => "visible = 1") +
|
||||
Relation.find_for_ways(way_ids, :conditions => "visible = 1")
|
||||
relations = Relation.find_for_nodes(visible_nodes.keys, :conditions => {:visible => true}) +
|
||||
Relation.find_for_ways(way_ids, :conditions => {:visible => true})
|
||||
|
||||
# we do not normally return the "other" partners referenced by an relation,
|
||||
# e.g. if we return a way A that is referenced by relation X, and there's
|
||||
# another way B also referenced, that is not returned. But we do make
|
||||
# an exception for cases where an relation references another *relation*;
|
||||
# in that case we return that as well (but we don't go recursive here)
|
||||
relations += Relation.find_for_relations(relations.collect { |r| r.id }, :conditions => "visible = 1")
|
||||
relations += Relation.find_for_relations(relations.collect { |r| r.id }, :conditions => {:visible => true})
|
||||
|
||||
# this "uniq" may be slightly inefficient; it may be better to first collect and output
|
||||
# all node-related relations, then find the *not yet covered* way-related ones etc.
|
||||
|
@ -204,6 +215,8 @@ class ApiController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Get a list of the tiles that have changed within a specified time
|
||||
# period
|
||||
def changes
|
||||
zoom = (params[:zoom] || '12').to_i
|
||||
|
||||
|
@ -212,12 +225,12 @@ class ApiController < ApplicationController
|
|||
endtime = Time.parse(params[:end])
|
||||
else
|
||||
hours = (params[:hours] || '1').to_i.hours
|
||||
endtime = Time.now
|
||||
endtime = Time.now.getutc
|
||||
starttime = endtime - hours
|
||||
end
|
||||
|
||||
if zoom >= 1 and zoom <= 16 and
|
||||
endtime >= starttime and endtime - starttime <= 24.hours
|
||||
endtime > starttime and endtime - starttime <= 24.hours
|
||||
mask = (1 << zoom) - 1
|
||||
|
||||
tiles = Node.count(:conditions => ["timestamp BETWEEN ? AND ?", starttime, endtime],
|
||||
|
@ -245,21 +258,32 @@ class ApiController < ApplicationController
|
|||
|
||||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
render :text => "Requested zoom is invalid, or the supplied start is after the end time, or the start duration is more than 24 hours", :status => :bad_request
|
||||
end
|
||||
end
|
||||
|
||||
# External apps that use the api are able to query the api to find out some
|
||||
# parameters of the API. It currently returns:
|
||||
# * minimum and maximum API versions that can be used.
|
||||
# * maximum area that can be requested in a bbox request in square degrees
|
||||
# * number of tracepoints that are returned in each tracepoints page
|
||||
def capabilities
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
|
||||
api = XML::Node.new 'api'
|
||||
version = XML::Node.new 'version'
|
||||
version['minimum'] = '0.5';
|
||||
version['maximum'] = '0.5';
|
||||
version['minimum'] = "#{API_VERSION}";
|
||||
version['maximum'] = "#{API_VERSION}";
|
||||
api << version
|
||||
area = XML::Node.new 'area'
|
||||
area['maximum'] = MAX_REQUEST_AREA.to_s;
|
||||
api << area
|
||||
tracepoints = XML::Node.new 'tracepoints'
|
||||
tracepoints['per_page'] = APP_CONFIG['tracepoints_per_page'].to_s
|
||||
api << tracepoints
|
||||
waynodes = XML::Node.new 'waynodes'
|
||||
waynodes['maximum'] = APP_CONFIG['max_number_of_way_nodes'].to_s
|
||||
api << waynodes
|
||||
|
||||
doc.root << api
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def authorize_web
|
||||
if session[:user]
|
||||
@user = User.find(session[:user], :conditions => "visible = 1")
|
||||
@user = User.find(session[:user], :conditions => {:visible => true})
|
||||
elsif session[:token]
|
||||
@user = User.authenticate(:token => session[:token])
|
||||
session[:user] = @user.id
|
||||
|
@ -22,7 +22,11 @@ class ApplicationController < ActionController::Base
|
|||
redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri unless @user
|
||||
end
|
||||
|
||||
def authorize(realm='Web Password', errormessage="Couldn't authenticate you")
|
||||
##
|
||||
# sets up the @user object for use by other methods. this is mostly called
|
||||
# from the authorize method, but can be called elsewhere if authorisation
|
||||
# is optional.
|
||||
def setup_user_auth
|
||||
username, passwd = get_auth_data # parse from headers
|
||||
# authenticate per-scheme
|
||||
if username.nil?
|
||||
|
@ -32,6 +36,11 @@ class ApplicationController < ActionController::Base
|
|||
else
|
||||
@user = User.authenticate(:username => username, :password => passwd) # basic auth
|
||||
end
|
||||
end
|
||||
|
||||
def authorize(realm='Web Password', errormessage="Couldn't authenticate you")
|
||||
# make the @user object from any auth sources we have
|
||||
setup_user_auth
|
||||
|
||||
# handle authenticate pass/fail
|
||||
unless @user
|
||||
|
@ -73,13 +82,21 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def require_public_data
|
||||
unless @user.data_public?
|
||||
response.headers['Error'] = "You must make your edits public to upload new data"
|
||||
render :nothing => true, :status => :forbidden
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Report and error to the user
|
||||
# (If anyone ever fixes Rails so it can set a http status "reason phrase",
|
||||
# rather than only a status code and having the web engine make up a
|
||||
# phrase from that, we can also put the error message into the status
|
||||
# message. For now, rails won't let us)
|
||||
def report_error(message)
|
||||
render :nothing => true, :status => :bad_request
|
||||
render :text => message, :status => :bad_request
|
||||
# Todo: some sort of escaping of problem characters in the message
|
||||
response.headers['Error'] = message
|
||||
end
|
||||
|
@ -90,6 +107,8 @@ private
|
|||
def get_auth_data
|
||||
if request.env.has_key? 'X-HTTP_AUTHORIZATION' # where mod_rewrite might have put it
|
||||
authdata = request.env['X-HTTP_AUTHORIZATION'].to_s.split
|
||||
elsif request.env.has_key? 'REDIRECT_X_HTTP_AUTHORIZATION' # mod_fcgi
|
||||
authdata = request.env['REDIRECT_X_HTTP_AUTHORIZATION'].to_s.split
|
||||
elsif request.env.has_key? 'HTTP_AUTHORIZATION' # regular location
|
||||
authdata = request.env['HTTP_AUTHORIZATION'].to_s.split
|
||||
end
|
||||
|
|
|
@ -7,103 +7,109 @@ class BrowseController < ApplicationController
|
|||
def start
|
||||
end
|
||||
|
||||
def index
|
||||
@nodes = Node.find(:all, :order => "timestamp DESC", :limit=> 20)
|
||||
end
|
||||
|
||||
|
||||
def relation
|
||||
begin
|
||||
@relation = Relation.find(params[:id])
|
||||
|
||||
@name = @relation.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @relation.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Relation | ' + (@name)
|
||||
@next = Relation.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @relation.id }] )
|
||||
@prev = Relation.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @relation.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
@relation = Relation.find(params[:id])
|
||||
|
||||
@name = @relation.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @relation.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Relation | ' + (@name)
|
||||
@next = Relation.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @relation.id }] )
|
||||
@prev = Relation.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @relation.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "relation"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
|
||||
def relation_history
|
||||
begin
|
||||
@relation = Relation.find(params[:id])
|
||||
@relation = Relation.find(params[:id])
|
||||
|
||||
@name = @relation.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @relation.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Relation History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
@name = @relation.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @relation.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Relation History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "relation"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
|
||||
def way
|
||||
begin
|
||||
@way = Way.find(params[:id])
|
||||
@way = Way.find(params[:id])
|
||||
|
||||
@name = @way.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @way.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Way | ' + (@name)
|
||||
@next = Way.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @way.id }] )
|
||||
@prev = Way.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @way.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
@name = @way.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @way.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Way | ' + (@name)
|
||||
@next = Way.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @way.id }] )
|
||||
@prev = Way.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @way.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "way"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
|
||||
def way_history
|
||||
begin
|
||||
@way = Way.find(params[:id])
|
||||
@way = Way.find(params[:id])
|
||||
|
||||
@name = @way.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @way.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Way History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
@name = @way.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @way.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Way History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "way"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
|
||||
def node
|
||||
begin
|
||||
@node = Node.find(params[:id])
|
||||
@node = Node.find(params[:id])
|
||||
|
||||
@name = @node.tags_as_hash['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @node.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Node | ' + (@name)
|
||||
@next = Node.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @node.id }] )
|
||||
@prev = Node.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @node.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
@name = @node.tags_as_hash['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @node.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Node | ' + (@name)
|
||||
@next = Node.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @node.id }] )
|
||||
@prev = Node.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @node.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "node"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
|
||||
def node_history
|
||||
begin
|
||||
@node = Node.find(params[:id])
|
||||
@node = Node.find(params[:id])
|
||||
|
||||
@name = @node.tags_as_hash['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @node.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Node History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
@name = @node.tags_as_hash['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @node.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Node History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "way"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
|
||||
def changeset
|
||||
@changeset = Changeset.find(params[:id])
|
||||
@node_pages, @nodes = paginate(:old_nodes, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'node_page')
|
||||
@way_pages, @ways = paginate(:old_ways, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'way_page')
|
||||
@relation_pages, @relations = paginate(:old_relations, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'relation_page')
|
||||
|
||||
@title = "Changeset | #{@changeset.id}"
|
||||
@next = Changeset.find(:first, :order => "id ASC", :conditions => [ "id > :id", { :id => @changeset.id }] )
|
||||
@prev = Changeset.find(:first, :order => "id DESC", :conditions => [ "id < :id", { :id => @changeset.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@type = "changeset"
|
||||
render :action => "not_found", :status => :not_found
|
||||
end
|
||||
end
|
||||
|
|
485
app/controllers/changeset_controller.rb
Normal file
485
app/controllers/changeset_controller.rb
Normal file
|
@ -0,0 +1,485 @@
|
|||
# The ChangesetController is the RESTful interface to Changeset objects
|
||||
|
||||
class ChangesetController < ApplicationController
|
||||
layout 'site'
|
||||
require 'xml/libxml'
|
||||
|
||||
session :off, :except => [:list, :list_user, :list_bbox]
|
||||
before_filter :authorize_web, :only => [:list, :list_user, :list_bbox]
|
||||
before_filter :authorize, :only => [:create, :update, :delete, :upload, :include, :close]
|
||||
before_filter :require_public_data, :only => [:create, :update, :delete, :upload, :include, :close]
|
||||
before_filter :check_api_writable, :only => [:create, :update, :delete, :upload, :include]
|
||||
before_filter :check_api_readable, :except => [:create, :update, :delete, :upload, :download, :query]
|
||||
after_filter :compress_output
|
||||
|
||||
# Help methods for checking boundary sanity and area size
|
||||
include MapBoundary
|
||||
|
||||
# Helper methods for checking consistency
|
||||
include ConsistencyValidations
|
||||
|
||||
# Create a changeset from XML.
|
||||
def create
|
||||
if request.put?
|
||||
cs = Changeset.from_xml(request.raw_post, true)
|
||||
|
||||
if cs
|
||||
cs.user_id = @user.id
|
||||
cs.save_with_tags!
|
||||
render :text => cs.id.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Return XML giving the basic info about the changeset. Does not
|
||||
# return anything about the nodes, ways and relations in the changeset.
|
||||
def read
|
||||
begin
|
||||
changeset = Changeset.find(params[:id])
|
||||
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# marks a changeset as closed. this may be called multiple times
|
||||
# on the same changeset, so is idempotent.
|
||||
def close
|
||||
unless request.put?
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
return
|
||||
end
|
||||
|
||||
changeset = Changeset.find(params[:id])
|
||||
check_changeset_consistency(changeset, @user)
|
||||
|
||||
# to close the changeset, we'll just set its closed_at time to
|
||||
# now. this might not be enough if there are concurrency issues,
|
||||
# but we'll have to wait and see.
|
||||
changeset.set_closed_time_now
|
||||
|
||||
changeset.save!
|
||||
render :nothing => true
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
|
||||
##
|
||||
# insert a (set of) points into a changeset bounding box. this can only
|
||||
# increase the size of the bounding box. this is a hint that clients can
|
||||
# set either before uploading a large number of changes, or changes that
|
||||
# the client (but not the server) knows will affect areas further away.
|
||||
def expand_bbox
|
||||
# only allow POST requests, because although this method is
|
||||
# idempotent, there is no "document" to PUT really...
|
||||
if request.post?
|
||||
cs = Changeset.find(params[:id])
|
||||
check_changeset_consistency(cs, @user)
|
||||
|
||||
# keep an array of lons and lats
|
||||
lon = Array.new
|
||||
lat = Array.new
|
||||
|
||||
# the request is in pseudo-osm format... this is kind-of an
|
||||
# abuse, maybe should change to some other format?
|
||||
doc = XML::Parser.string(request.raw_post).parse
|
||||
doc.find("//osm/node").each do |n|
|
||||
lon << n['lon'].to_f * GeoRecord::SCALE
|
||||
lat << n['lat'].to_f * GeoRecord::SCALE
|
||||
end
|
||||
|
||||
# add the existing bounding box to the lon-lat array
|
||||
lon << cs.min_lon unless cs.min_lon.nil?
|
||||
lat << cs.min_lat unless cs.min_lat.nil?
|
||||
lon << cs.max_lon unless cs.max_lon.nil?
|
||||
lat << cs.max_lat unless cs.max_lat.nil?
|
||||
|
||||
# collapse the arrays to minimum and maximum
|
||||
cs.min_lon, cs.min_lat, cs.max_lon, cs.max_lat =
|
||||
lon.min, lat.min, lon.max, lat.max
|
||||
|
||||
# save the larger bounding box and return the changeset, which
|
||||
# will include the bigger bounding box.
|
||||
cs.save!
|
||||
render :text => cs.to_xml.to_s, :content_type => "text/xml"
|
||||
|
||||
else
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
end
|
||||
|
||||
rescue LibXML::XML::Error, ArgumentError => ex
|
||||
raise OSM::APIBadXMLError.new("osm", xml, ex.message)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
|
||||
##
|
||||
# Upload a diff in a single transaction.
|
||||
#
|
||||
# This means that each change within the diff must succeed, i.e: that
|
||||
# each version number mentioned is still current. Otherwise the entire
|
||||
# transaction *must* be rolled back.
|
||||
#
|
||||
# Furthermore, each element in the diff can only reference the current
|
||||
# changeset.
|
||||
#
|
||||
# Returns: a diffResult document, as described in
|
||||
# http://wiki.openstreetmap.org/index.php/OSM_Protocol_Version_0.6
|
||||
def upload
|
||||
# only allow POST requests, as the upload method is most definitely
|
||||
# not idempotent, as several uploads with placeholder IDs will have
|
||||
# different side-effects.
|
||||
# see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2
|
||||
unless request.post?
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
return
|
||||
end
|
||||
|
||||
changeset = Changeset.find(params[:id])
|
||||
check_changeset_consistency(changeset, @user)
|
||||
|
||||
diff_reader = DiffReader.new(request.raw_post, changeset)
|
||||
Changeset.transaction do
|
||||
result = diff_reader.commit
|
||||
render :text => result.to_s, :content_type => "text/xml"
|
||||
end
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
|
||||
##
|
||||
# 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 download
|
||||
changeset = Changeset.find(params[:id])
|
||||
|
||||
# get all the elements in the changeset and stick them in a big array.
|
||||
elements = [changeset.old_nodes,
|
||||
changeset.old_ways,
|
||||
changeset.old_relations].flatten
|
||||
|
||||
# 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! do |a, b|
|
||||
if (a.timestamp == b.timestamp)
|
||||
a.version <=> b.version
|
||||
else
|
||||
a.timestamp <=> b.timestamp
|
||||
end
|
||||
end
|
||||
|
||||
# create an osmChange document for the output
|
||||
result = OSM::API.new.get_xml_doc
|
||||
result.root.name = "osmChange"
|
||||
|
||||
# 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.
|
||||
elements.each do |elt|
|
||||
result.root <<
|
||||
if (elt.version == 1)
|
||||
# first version, so it must be newly-created.
|
||||
created = XML::Node.new "create"
|
||||
created << elt.to_xml_node
|
||||
else
|
||||
# get the previous version from the element history
|
||||
prev_elt = elt.class.find(:first, :conditions =>
|
||||
['id = ? and version = ?',
|
||||
elt.id, elt.version])
|
||||
unless elt.visible
|
||||
# if the element isn't visible then it must have been deleted, so
|
||||
# output the *previous* XML
|
||||
deleted = XML::Node.new "delete"
|
||||
deleted << prev_elt.to_xml_node
|
||||
else
|
||||
# must be a modify, for which we don't need the previous version
|
||||
# yet...
|
||||
modified = XML::Node.new "modify"
|
||||
modified << elt.to_xml_node
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
render :text => result.to_s, :content_type => "text/xml"
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
|
||||
##
|
||||
# query changesets by bounding box, time, user or open/closed status.
|
||||
def query
|
||||
# create the conditions that the user asked for. some or all of
|
||||
# these may be nil.
|
||||
conditions = conditions_bbox(params['bbox'])
|
||||
conditions = cond_merge conditions, conditions_user(params['user'])
|
||||
conditions = cond_merge conditions, conditions_time(params['time'])
|
||||
conditions = cond_merge conditions, conditions_open(params['open'])
|
||||
conditions = cond_merge conditions, conditions_closed(params['closed'])
|
||||
|
||||
# create the results document
|
||||
results = OSM::API.new.get_xml_doc
|
||||
|
||||
# add all matching changesets to the XML results document
|
||||
Changeset.find(:all,
|
||||
:conditions => conditions,
|
||||
:limit => 100,
|
||||
:order => 'created_at desc').each do |cs|
|
||||
results.root << cs.to_xml_node
|
||||
end
|
||||
|
||||
render :text => results.to_s, :content_type => "text/xml"
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
|
||||
##
|
||||
# updates a changeset's tags. none of the changeset's attributes are
|
||||
# user-modifiable, so they will be ignored.
|
||||
#
|
||||
# changesets are not (yet?) versioned, so we don't have to deal with
|
||||
# history tables here. changesets are locked to a single user, however.
|
||||
#
|
||||
# after succesful update, returns the XML of the changeset.
|
||||
def update
|
||||
# request *must* be a PUT.
|
||||
unless request.put?
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
return
|
||||
end
|
||||
|
||||
changeset = Changeset.find(params[:id])
|
||||
new_changeset = Changeset.from_xml(request.raw_post)
|
||||
|
||||
unless new_changeset.nil?
|
||||
check_changeset_consistency(changeset, @user)
|
||||
changeset.update_from(new_changeset, @user)
|
||||
render :text => changeset.to_xml, :mime_type => "text/xml"
|
||||
else
|
||||
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
|
||||
|
||||
|
||||
##
|
||||
# list edits (open changesets) in reverse chronological order
|
||||
def list
|
||||
conditions = conditions_nonempty
|
||||
|
||||
|
||||
# @changesets = Changeset.find(:all, :order => "closed_at DESC", :conditions => ['closed_at < ?', DateTime.now], :limit=> 20)
|
||||
|
||||
|
||||
#@edit_pages, @edits = paginate(:changesets,
|
||||
# :include => [:user, :changeset_tags],
|
||||
# :conditions => conditions,
|
||||
# :order => "changesets.created_at DESC",
|
||||
# :per_page => 20)
|
||||
#
|
||||
|
||||
@edits = Changeset.find(:all,
|
||||
:order => "changesets.created_at DESC",
|
||||
:conditions => conditions,
|
||||
:limit => 20)
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# list edits (changesets) belonging to a user
|
||||
def list_user
|
||||
user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
|
||||
|
||||
if user
|
||||
@display_name = user.display_name
|
||||
if not user.data_public? and @user != user
|
||||
@edits = nil
|
||||
render
|
||||
else
|
||||
conditions = cond_merge conditions, ['user_id = ?', user.id]
|
||||
conditions = cond_merge conditions, conditions_nonempty
|
||||
@edit_pages, @edits = paginate(:changesets,
|
||||
:include => [:user, :changeset_tags],
|
||||
:conditions => conditions,
|
||||
:order => "changesets.created_at DESC",
|
||||
:per_page => 20)
|
||||
end
|
||||
else
|
||||
@not_found_user = params[:display_name]
|
||||
render :template => 'user/no_such_user', :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# list changesets in a bbox
|
||||
def list_bbox
|
||||
# support 'bbox' param or alternatively 'minlon', 'minlat' etc
|
||||
if params['bbox']
|
||||
bbox = params['bbox']
|
||||
elsif params['minlon'] and params['minlat'] and params['maxlon'] and params['maxlat']
|
||||
bbox = h(params['minlon']) + ',' + h(params['minlat']) + ',' + h(params['maxlon']) + ',' + h(params['maxlat'])
|
||||
else
|
||||
#TODO: fix bugs in location determination for history tab (and other tabs) then uncomment this redirect
|
||||
#redirect_to :action => 'list'
|
||||
end
|
||||
|
||||
conditions = conditions_bbox(bbox);
|
||||
conditions = cond_merge conditions, conditions_nonempty
|
||||
|
||||
@edit_pages, @edits = paginate(:changesets,
|
||||
:include => [:user, :changeset_tags],
|
||||
:conditions => conditions,
|
||||
:order => "changesets.created_at DESC",
|
||||
:per_page => 20)
|
||||
|
||||
@bbox = sanitise_boundaries(bbox.split(/,/)) unless bbox==nil
|
||||
end
|
||||
|
||||
private
|
||||
#------------------------------------------------------------
|
||||
# utility functions below.
|
||||
#------------------------------------------------------------
|
||||
|
||||
##
|
||||
# merge two conditions
|
||||
def cond_merge(a, b)
|
||||
if a and b
|
||||
a_str = a.shift
|
||||
b_str = b.shift
|
||||
return [ a_str + " AND " + b_str ] + a + b
|
||||
elsif a
|
||||
return a
|
||||
else b
|
||||
return b
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# if a bounding box was specified then parse it and do some sanity
|
||||
# checks. this is mostly the same as the map call, but without the
|
||||
# area restriction.
|
||||
def conditions_bbox(bbox)
|
||||
unless bbox.nil?
|
||||
raise OSM::APIBadUserInput.new("Bounding box should be min_lon,min_lat,max_lon,max_lat") unless bbox.count(',') == 3
|
||||
bbox = sanitise_boundaries(bbox.split(/,/))
|
||||
raise OSM::APIBadUserInput.new("Minimum longitude should be less than maximum.") unless bbox[0] <= bbox[2]
|
||||
raise OSM::APIBadUserInput.new("Minimum latitude should be less than maximum.") unless bbox[1] <= bbox[3]
|
||||
return ['min_lon < ? and max_lon > ? and min_lat < ? and max_lat > ?',
|
||||
bbox[2] * GeoRecord::SCALE, bbox[0] * GeoRecord::SCALE, bbox[3]* GeoRecord::SCALE, bbox[1] * GeoRecord::SCALE]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# restrict changesets to those by a particular user
|
||||
def conditions_user(user)
|
||||
unless user.nil?
|
||||
# user input checking, we don't have any UIDs < 1
|
||||
raise OSM::APIBadUserInput.new("invalid user ID") if user.to_i < 1
|
||||
|
||||
u = User.find(user.to_i)
|
||||
# should be able to get changesets of public users only, or
|
||||
# our own changesets regardless of public-ness.
|
||||
unless u.data_public?
|
||||
# get optional user auth stuff so that users can see their own
|
||||
# changesets if they're non-public
|
||||
setup_user_auth
|
||||
|
||||
raise OSM::APINotFoundError if @user.nil? or @user.id != u.id
|
||||
end
|
||||
return ['user_id = ?', u.id]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# restrict changes to those closed during a particular time period
|
||||
def conditions_time(time)
|
||||
unless time.nil?
|
||||
# if there is a range, i.e: comma separated, then the first is
|
||||
# low, second is high - same as with bounding boxes.
|
||||
if time.count(',') == 1
|
||||
# check that we actually have 2 elements in the array
|
||||
times = time.split(/,/)
|
||||
raise OSM::APIBadUserInput.new("bad time range") if times.size != 2
|
||||
|
||||
from, to = times.collect { |t| DateTime.parse(t) }
|
||||
return ['closed_at >= ? and created_at <= ?', from, to]
|
||||
else
|
||||
# if there is no comma, assume its a lower limit on time
|
||||
return ['closed_at >= ?', DateTime.parse(time)]
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
# stupid DateTime seems to throw both of these for bad parsing, so
|
||||
# we have to catch both and ensure the correct code path is taken.
|
||||
rescue ArgumentError => ex
|
||||
raise OSM::APIBadUserInput.new(ex.message.to_s)
|
||||
rescue RuntimeError => ex
|
||||
raise OSM::APIBadUserInput.new(ex.message.to_s)
|
||||
end
|
||||
|
||||
##
|
||||
# return changesets which are open (haven't been closed yet)
|
||||
# we do this by seeing if the 'closed at' time is in the future. Also if we've
|
||||
# hit the maximum number of changes then it counts as no longer open.
|
||||
# if parameter 'open' is nill then open and closed changsets are returned
|
||||
def conditions_open(open)
|
||||
return open.nil? ? nil : ['closed_at >= ? and num_changes <= ?',
|
||||
Time.now.getutc, Changeset::MAX_ELEMENTS]
|
||||
end
|
||||
|
||||
##
|
||||
# query changesets which are closed
|
||||
# ('closed at' time has passed or changes limit is hit)
|
||||
def conditions_closed(closed)
|
||||
return closed.nil? ? nil : ['closed_at < ? and num_changes > ?',
|
||||
Time.now.getutc, Changeset::MAX_ELEMENTS]
|
||||
end
|
||||
|
||||
##
|
||||
# eliminate empty changesets (where the bbox has not been set)
|
||||
# this should be applied to all changeset list displays
|
||||
def conditions_nonempty()
|
||||
return ['min_lat IS NOT NULL']
|
||||
end
|
||||
|
||||
end
|
9
app/controllers/changeset_tag_controller.rb
Normal file
9
app/controllers/changeset_tag_controller.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class ChangesetTagController < ApplicationController
|
||||
layout 'site'
|
||||
|
||||
def search
|
||||
@tags = ChangesetTag.find(:all, :limit => 11, :conditions => ["match(v) against (?)", params[:query][:query].to_s] )
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -39,6 +39,8 @@ class DiaryEntryController < ApplicationController
|
|||
redirect_to :controller => 'diary_entry', :action => 'view', :id => params[:id]
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :action => "no_such_entry", :status => :not_found
|
||||
end
|
||||
|
||||
def comment
|
||||
|
@ -55,7 +57,7 @@ class DiaryEntryController < ApplicationController
|
|||
|
||||
def list
|
||||
if params[:display_name]
|
||||
@this_user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1")
|
||||
@this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
|
||||
|
||||
if @this_user
|
||||
@title = @this_user.display_name + "'s diary"
|
||||
|
@ -71,7 +73,7 @@ class DiaryEntryController < ApplicationController
|
|||
else
|
||||
@title = "Users' diaries"
|
||||
@entry_pages, @entries = paginate(:diary_entries, :include => :user,
|
||||
:conditions => "users.visible = 1",
|
||||
:conditions => ["users.visible = ?", true],
|
||||
:order => 'created_at DESC',
|
||||
:per_page => 20)
|
||||
end
|
||||
|
@ -79,13 +81,13 @@ class DiaryEntryController < ApplicationController
|
|||
|
||||
def rss
|
||||
if params[:display_name]
|
||||
user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1")
|
||||
user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
|
||||
|
||||
if user
|
||||
@entries = DiaryEntry.find(:all, :conditions => ['user_id = ?', user.id], :order => 'created_at DESC', :limit => 20)
|
||||
@title = "OpenStreetMap diary entries for #{user.display_name}"
|
||||
@description = "Recent OpenStreetmap diary entries from #{user.display_name}"
|
||||
@link = "http://www.openstreetmap.org/user/#{user.display_name}/diary"
|
||||
@link = "http://#{SERVER_URL}/user/#{user.display_name}/diary"
|
||||
|
||||
render :content_type => Mime::RSS
|
||||
else
|
||||
|
@ -93,21 +95,22 @@ class DiaryEntryController < ApplicationController
|
|||
end
|
||||
else
|
||||
@entries = DiaryEntry.find(:all, :include => :user,
|
||||
:conditions => "users.visible = 1",
|
||||
:conditions => ["users.visible = ?", true],
|
||||
:order => 'created_at DESC', :limit => 20)
|
||||
@title = "OpenStreetMap diary entries"
|
||||
@description = "Recent diary entries from users of OpenStreetMap"
|
||||
@link = "http://www.openstreetmap.org/diary"
|
||||
@link = "http://#{SERVER_URL}/diary"
|
||||
|
||||
render :content_type => Mime::RSS
|
||||
end
|
||||
end
|
||||
|
||||
def view
|
||||
user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1")
|
||||
user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
|
||||
|
||||
if user
|
||||
@entry = DiaryEntry.find(:first, :conditions => ['user_id = ? AND id = ?', user.id, params[:id]])
|
||||
@title = "Users' diaries | #{params[:display_name]}"
|
||||
else
|
||||
@not_found_user = params[:display_name]
|
||||
|
||||
|
|
|
@ -2,18 +2,24 @@ class ExportController < ApplicationController
|
|||
def start
|
||||
end
|
||||
|
||||
#When the user clicks 'Export' we redirect to a URL which generates the export download
|
||||
def finish
|
||||
bbox = BoundingBox.new(params[:minlon], params[:minlat], params[:maxlon], params[:maxlat])
|
||||
format = params[:format]
|
||||
|
||||
if format == "osm"
|
||||
#redirect to API map get
|
||||
redirect_to "http://api.openstreetmap.org/api/#{API_VERSION}/map?bbox=#{bbox}"
|
||||
|
||||
elsif format == "mapnik"
|
||||
#redirect to a special 'export' cgi script
|
||||
format = params[:mapnik_format]
|
||||
scale = params[:mapnik_scale]
|
||||
|
||||
redirect_to "http://tile.openstreetmap.org/cgi-bin/export?bbox=#{bbox}&scale=#{scale}&format=#{format}"
|
||||
|
||||
elsif format == "osmarender"
|
||||
#redirect to the t@h 'MapOf' service
|
||||
format = params[:osmarender_format]
|
||||
zoom = params[:osmarender_zoom].to_i
|
||||
width = bbox.slippy_width(zoom).to_i
|
||||
|
|
|
@ -6,13 +6,18 @@ class MessageController < ApplicationController
|
|||
before_filter :check_database_readable
|
||||
before_filter :check_database_writable, :only => [:new, :reply, :mark]
|
||||
|
||||
# Allow the user to write a new message to another user. This action also
|
||||
# deals with the sending of that message to the other user when the user
|
||||
# clicks send.
|
||||
# The user_id param is the id of the user that the message is being sent to.
|
||||
def new
|
||||
@title = 'send message'
|
||||
@to_user = User.find(params[:user_id])
|
||||
if params[:message]
|
||||
@message = Message.new(params[:message])
|
||||
@message.to_user_id = params[:user_id]
|
||||
@message.to_user_id = @to_user.id
|
||||
@message.from_user_id = @user.id
|
||||
@message.sent_on = Time.now
|
||||
@message.sent_on = Time.now.getutc
|
||||
|
||||
if @message.save
|
||||
flash[:notice] = 'Message sent'
|
||||
|
@ -22,27 +27,32 @@ class MessageController < ApplicationController
|
|||
else
|
||||
@title = params[:title]
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :action => 'no_such_user', :status => :not_found
|
||||
end
|
||||
|
||||
# Allow the user to reply to another message.
|
||||
def reply
|
||||
message = Message.find(params[:message_id], :conditions => ["to_user_id = ? or from_user_id = ?", @user.id, @user.id ])
|
||||
@body = "On #{message.sent_on} #{message.sender.display_name} wrote:\n\n#{message.body.gsub(/^/, '> ')}"
|
||||
@title = "Re: #{message.title.sub(/^Re:\s*/, '')}"
|
||||
@user_id = message.from_user_id
|
||||
@to_user = User.find(message.from_user_id)
|
||||
render :action => 'new'
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
render :action => 'no_such_user', :status => :not_found
|
||||
end
|
||||
|
||||
# Show a message
|
||||
def read
|
||||
@title = 'read message'
|
||||
@message = Message.find(params[:message_id], :conditions => ["to_user_id = ? or from_user_id = ?", @user.id, @user.id ])
|
||||
@message.message_read = 1 if @message.to_user_id == @user.id
|
||||
@message.message_read = true if @message.to_user_id == @user.id
|
||||
@message.save
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
render :action => 'no_such_user', :status => :not_found
|
||||
end
|
||||
|
||||
# Display the list of messages that have been sent to the user.
|
||||
def inbox
|
||||
@title = 'inbox'
|
||||
if @user and params[:display_name] == @user.display_name
|
||||
|
@ -51,6 +61,7 @@ class MessageController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Display the list of messages that the user has sent to other users.
|
||||
def outbox
|
||||
@title = 'outbox'
|
||||
if @user and params[:display_name] == @user.display_name
|
||||
|
@ -59,15 +70,16 @@ class MessageController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Set the message as being read or unread.
|
||||
def mark
|
||||
if params[:message_id]
|
||||
id = params[:message_id]
|
||||
message = Message.find_by_id(id)
|
||||
if params[:mark] == 'unread'
|
||||
message_read = 0
|
||||
message_read = false
|
||||
mark_type = 'unread'
|
||||
else
|
||||
message_read = 1
|
||||
message_read = true
|
||||
mark_type = 'read'
|
||||
end
|
||||
message.message_read = message_read
|
||||
|
@ -76,5 +88,7 @@ class MessageController < ApplicationController
|
|||
redirect_to :controller => 'message', :action => 'inbox', :display_name => @user.display_name
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :action => 'no_such_user', :status => :not_found
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,26 +5,28 @@ class NodeController < ApplicationController
|
|||
|
||||
session :off
|
||||
before_filter :authorize, :only => [:create, :update, :delete]
|
||||
before_filter :require_public_data, :only => [:create, :update, :delete]
|
||||
before_filter :check_api_writable, :only => [:create, :update, :delete]
|
||||
before_filter :check_api_readable, :except => [:create, :update, :delete]
|
||||
after_filter :compress_output
|
||||
|
||||
# Create a node from XML.
|
||||
def create
|
||||
if request.put?
|
||||
node = Node.from_xml(request.raw_post, true)
|
||||
begin
|
||||
if request.put?
|
||||
node = Node.from_xml(request.raw_post, true)
|
||||
|
||||
if node
|
||||
node.user_id = @user.id
|
||||
node.visible = true
|
||||
node.save_with_history!
|
||||
|
||||
render :text => node.id.to_s, :content_type => "text/plain"
|
||||
if node
|
||||
node.create_with_history @user
|
||||
render :text => node.id.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -32,7 +34,7 @@ class NodeController < ApplicationController
|
|||
def read
|
||||
begin
|
||||
node = Node.find(params[:id])
|
||||
if node.visible
|
||||
if node.visible?
|
||||
response.headers['Last-Modified'] = node.timestamp.rfc822
|
||||
render :text => node.to_xml.to_s, :content_type => "text/xml"
|
||||
else
|
||||
|
@ -42,7 +44,7 @@ class NodeController < ApplicationController
|
|||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Update a node from given XML
|
||||
def update
|
||||
begin
|
||||
|
@ -50,49 +52,40 @@ class NodeController < ApplicationController
|
|||
new_node = Node.from_xml(request.raw_post)
|
||||
|
||||
if new_node and new_node.id == node.id
|
||||
node.user_id = @user.id
|
||||
node.latitude = new_node.latitude
|
||||
node.longitude = new_node.longitude
|
||||
node.tags = new_node.tags
|
||||
node.visible = true
|
||||
node.save_with_history!
|
||||
node.update_from(new_node, @user)
|
||||
render :text => node.version.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
render :nothing => true
|
||||
# Delete a node. Doesn't actually delete it, but retains its history
|
||||
# in a wiki-like way. We therefore treat it like an update, so the delete
|
||||
# method returns the new version number.
|
||||
def delete
|
||||
begin
|
||||
node = Node.find(params[:id])
|
||||
new_node = Node.from_xml(request.raw_post)
|
||||
|
||||
if new_node and new_node.id == node.id
|
||||
node.delete_with_history!(new_node, @user)
|
||||
render :text => node.version.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
end
|
||||
|
||||
# Delete a node. Doesn't actually delete it, but retains its history in a wiki-like way.
|
||||
# FIXME remove all the fricking SQL
|
||||
def delete
|
||||
begin
|
||||
node = Node.find(params[:id])
|
||||
|
||||
if node.visible
|
||||
if WayNode.find(:first, :joins => "INNER JOIN current_ways ON current_ways.id = current_way_nodes.id", :conditions => [ "current_ways.visible = 1 AND current_way_nodes.node_id = ?", node.id ])
|
||||
render :text => "", :status => :precondition_failed
|
||||
elsif RelationMember.find(:first, :joins => "INNER JOIN current_relations ON current_relations.id=current_relation_members.id", :conditions => [ "visible = 1 AND member_type='node' and member_id=?", params[:id]])
|
||||
render :text => "", :status => :precondition_failed
|
||||
else
|
||||
node.user_id = @user.id
|
||||
node.visible = 0
|
||||
node.save_with_history!
|
||||
|
||||
render :nothing => true
|
||||
end
|
||||
else
|
||||
render :text => "", :status => :gone
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
# WTF does this do?
|
||||
# Dump the details on many nodes whose ids are given in the "nodes" parameter.
|
||||
def nodes
|
||||
ids = params['nodes'].split(',').collect { |n| n.to_i }
|
||||
|
||||
|
|
|
@ -22,4 +22,21 @@ class OldNodeController < ApplicationController
|
|||
render :nothing => true, :status => :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
def version
|
||||
begin
|
||||
old_node = OldNode.find(:first, :conditions => {:id => params[:id], :version => params[:version]} )
|
||||
|
||||
response.headers['Last-Modified'] = old_node.timestamp.rfc822
|
||||
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
doc.root << old_node.to_xml_node
|
||||
|
||||
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
|
||||
|
|
|
@ -2,6 +2,7 @@ class OldRelationController < ApplicationController
|
|||
require 'xml/libxml'
|
||||
|
||||
session :off
|
||||
before_filter :check_api_readable
|
||||
after_filter :compress_output
|
||||
|
||||
def history
|
||||
|
@ -20,4 +21,21 @@ class OldRelationController < ApplicationController
|
|||
render :nothing => true, :status => :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
def version
|
||||
begin
|
||||
old_relation = OldRelation.find(:first, :conditions => {:id => params[:id], :version => params[:version]} )
|
||||
|
||||
response.headers['Last-Modified'] = old_relation.timestamp.rfc822
|
||||
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
doc.root << old_relation.to_xml_node
|
||||
|
||||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue
|
||||
render :nothing => true, :status => :internetal_service_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ class OldWayController < ApplicationController
|
|||
|
||||
way.old_ways.each do |old_way|
|
||||
doc.root << old_way.to_xml_node
|
||||
end
|
||||
end
|
||||
|
||||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
|
@ -22,4 +22,21 @@ class OldWayController < ApplicationController
|
|||
render :nothing => true, :status => :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
def version
|
||||
begin
|
||||
old_way = OldWay.find(:first, :conditions => {:id => params[:id], :version => params[:version]} )
|
||||
|
||||
response.headers['Last-Modified'] = old_way.timestamp.rfc822
|
||||
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
doc.root << old_way.to_xml_node
|
||||
|
||||
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
|
||||
|
|
|
@ -3,28 +3,29 @@ class RelationController < ApplicationController
|
|||
|
||||
session :off
|
||||
before_filter :authorize, :only => [:create, :update, :delete]
|
||||
before_filter :require_public_data, :only => [:create, :update, :delete]
|
||||
before_filter :check_api_writable, :only => [:create, :update, :delete]
|
||||
before_filter :check_api_readable, :except => [:create, :update, :delete]
|
||||
after_filter :compress_output
|
||||
|
||||
def create
|
||||
if request.put?
|
||||
relation = Relation.from_xml(request.raw_post, true)
|
||||
begin
|
||||
if request.put?
|
||||
relation = Relation.from_xml(request.raw_post, true)
|
||||
|
||||
if relation
|
||||
if !relation.preconditions_ok?
|
||||
render :text => "", :status => :precondition_failed
|
||||
else
|
||||
relation.user_id = @user.id
|
||||
relation.save_with_history!
|
||||
|
||||
render :text => relation.id.to_s, :content_type => "text/plain"
|
||||
end
|
||||
# We assume that an exception has been thrown if there was an error
|
||||
# generating the relation
|
||||
#if relation
|
||||
relation.create_with_history @user
|
||||
render :text => relation.id.to_s, :content_type => "text/plain"
|
||||
#else
|
||||
# render :text => "Couldn't get turn the input into a relation.", :status => :bad_request
|
||||
#end
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -45,56 +46,38 @@ class RelationController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
logger.debug request.raw_post
|
||||
begin
|
||||
relation = Relation.find(params[:id])
|
||||
new_relation = Relation.from_xml(request.raw_post)
|
||||
|
||||
if new_relation and new_relation.id == relation.id
|
||||
if !new_relation.preconditions_ok?
|
||||
render :text => "", :status => :precondition_failed
|
||||
else
|
||||
relation.user_id = @user.id
|
||||
relation.tags = new_relation.tags
|
||||
relation.members = new_relation.members
|
||||
relation.visible = true
|
||||
relation.save_with_history!
|
||||
|
||||
render :nothing => true
|
||||
end
|
||||
relation.update_from new_relation, @user
|
||||
render :text => relation.version.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue
|
||||
render :nothing => true, :status => :internal_server_error
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
end
|
||||
end
|
||||
|
||||
def delete
|
||||
#XXX check if member somewhere!
|
||||
begin
|
||||
relation = Relation.find(params[:id])
|
||||
|
||||
if relation.visible
|
||||
if RelationMember.find(:first, :joins => "INNER JOIN current_relations ON current_relations.id=current_relation_members.id", :conditions => [ "visible = 1 AND member_type='relation' and member_id=?", params[:id]])
|
||||
render :text => "", :status => :precondition_failed
|
||||
else
|
||||
relation.user_id = @user.id
|
||||
relation.tags = []
|
||||
relation.members = []
|
||||
relation.visible = false
|
||||
relation.save_with_history!
|
||||
|
||||
render :nothing => true
|
||||
end
|
||||
new_relation = Relation.from_xml(request.raw_post)
|
||||
if new_relation and new_relation.id == relation.id
|
||||
relation.delete_with_history!(new_relation, @user)
|
||||
render :text => relation.version.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :text => "", :status => :gone
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
rescue
|
||||
render :nothing => true, :status => :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -115,12 +98,12 @@ class RelationController < ApplicationController
|
|||
# first collect nodes, ways, and relations referenced by this relation.
|
||||
|
||||
ways = Way.find_by_sql("select w.* from current_ways w,current_relation_members rm where "+
|
||||
"rm.member_type='way' and rm.member_id=w.id and rm.id=#{relation.id}");
|
||||
"rm.member_type='Way' and rm.member_id=w.id and rm.id=#{relation.id}");
|
||||
nodes = Node.find_by_sql("select n.* from current_nodes n,current_relation_members rm where "+
|
||||
"rm.member_type='node' and rm.member_id=n.id and rm.id=#{relation.id}");
|
||||
"rm.member_type='Node' and rm.member_id=n.id and rm.id=#{relation.id}");
|
||||
# note query is built to exclude self just in case.
|
||||
relations = Relation.find_by_sql("select r.* from current_relations r,current_relation_members rm where "+
|
||||
"rm.member_type='relation' and rm.member_id=r.id and rm.id=#{relation.id} and r.id<>rm.id");
|
||||
"rm.member_type='Relation' and rm.member_id=r.id and rm.id=#{relation.id} and r.id<>rm.id");
|
||||
|
||||
# now additionally collect nodes referenced by ways. Note how we recursively
|
||||
# evaluate ways but NOT relations.
|
||||
|
@ -160,8 +143,7 @@ class RelationController < ApplicationController
|
|||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
|
||||
else
|
||||
|
||||
render :text => "", :status => :gone
|
||||
render :nothing => true, :status => :gone
|
||||
end
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
|
@ -184,27 +166,29 @@ class RelationController < ApplicationController
|
|||
|
||||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
render :text => "You need to supply a comma separated list of ids.", :status => :bad_request
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :text => "Could not find one of the relations", :status => :not_found
|
||||
end
|
||||
|
||||
def relations_for_way
|
||||
relations_for_object("way")
|
||||
relations_for_object("Way")
|
||||
end
|
||||
def relations_for_node
|
||||
relations_for_object("node")
|
||||
relations_for_object("Node")
|
||||
end
|
||||
def relations_for_relation
|
||||
relations_for_object("relation")
|
||||
relations_for_object("Relation")
|
||||
end
|
||||
|
||||
def relations_for_object(objtype)
|
||||
relationids = RelationMember.find(:all, :conditions => ['member_type=? and member_id=?', objtype, params[:id]]).collect { |ws| ws.id }.uniq
|
||||
relationids = RelationMember.find(:all, :conditions => ['member_type=? and member_id=?', objtype, params[:id]]).collect { |ws| ws.id[0] }.uniq
|
||||
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
|
||||
Relation.find(relationids).each do |relation|
|
||||
doc.root << relation.to_xml_node
|
||||
doc.root << relation.to_xml_node if relation.visible
|
||||
end
|
||||
|
||||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
class TraceController < ApplicationController
|
||||
layout 'site'
|
||||
|
||||
before_filter :authorize_web
|
||||
before_filter :require_user, :only => [:mine, :edit, :delete, :make_public]
|
||||
before_filter :authorize_web
|
||||
before_filter :require_user, :only => [:mine, :create, :edit, :delete, :make_public]
|
||||
before_filter :authorize, :only => [:api_details, :api_data, :api_create]
|
||||
before_filter :check_database_readable, :except => [:api_details, :api_data, :api_create]
|
||||
before_filter :check_database_writable, :only => [:create, :edit, :delete, :make_public]
|
||||
|
@ -15,7 +15,12 @@ class TraceController < ApplicationController
|
|||
# from display name, pick up user id if one user's traces only
|
||||
display_name = params[:display_name]
|
||||
if target_user.nil? and !display_name.blank?
|
||||
target_user = User.find(:first, :conditions => [ "visible = 1 and display_name = ?", display_name])
|
||||
target_user = User.find(:first, :conditions => [ "visible = ? and display_name = ?", true, display_name])
|
||||
if target_user.nil?
|
||||
@not_found_user = display_name
|
||||
render :action => 'no_such_user', :status => :not_found
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# set title
|
||||
|
@ -36,15 +41,15 @@ class TraceController < ApplicationController
|
|||
# 4 - user's traces, not logged in as that user = all user's public traces
|
||||
if target_user.nil? # all traces
|
||||
if @user
|
||||
conditions = ["(gpx_files.public = 1 OR gpx_files.user_id = ?)", @user.id] #1
|
||||
conditions = ["(gpx_files.public = ? OR gpx_files.user_id = ?)", true, @user.id] #1
|
||||
else
|
||||
conditions = ["gpx_files.public = 1"] #2
|
||||
conditions = ["gpx_files.public = ?", true] #2
|
||||
end
|
||||
else
|
||||
if @user and @user == target_user
|
||||
conditions = ["gpx_files.user_id = ?", @user.id] #3 (check vs user id, so no join + can't pick up non-public traces by changing name)
|
||||
else
|
||||
conditions = ["gpx_files.public = 1 AND gpx_files.user_id = ?", target_user.id] #4
|
||||
conditions = ["gpx_files.public = ? AND gpx_files.user_id = ?", true, target_user.id] #4
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -55,7 +60,8 @@ class TraceController < ApplicationController
|
|||
conditions[0] += " AND gpx_files.id IN (#{files.join(',')})"
|
||||
end
|
||||
|
||||
conditions[0] += " AND gpx_files.visible = 1"
|
||||
conditions[0] += " AND gpx_files.visible = ?"
|
||||
conditions << true
|
||||
|
||||
@trace_pages, @traces = paginate(:traces,
|
||||
:include => [:user, :tags],
|
||||
|
@ -100,26 +106,28 @@ class TraceController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
logger.info(params[:trace][:gpx_file].class.name)
|
||||
if params[:trace][:gpx_file].respond_to?(:read)
|
||||
do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
|
||||
params[:trace][:description], params[:trace][:public])
|
||||
if params[:trace]
|
||||
logger.info(params[:trace][:gpx_file].class.name)
|
||||
if params[:trace][:gpx_file].respond_to?(:read)
|
||||
do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
|
||||
params[:trace][:description], params[:trace][:public])
|
||||
|
||||
if @trace.id
|
||||
logger.info("id is #{@trace.id}")
|
||||
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."
|
||||
if @trace.id
|
||||
logger.info("id is #{@trace.id}")
|
||||
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."
|
||||
|
||||
redirect_to :action => 'mine'
|
||||
redirect_to :action => 'mine'
|
||||
end
|
||||
else
|
||||
@trace = Trace.new({:name => "Dummy",
|
||||
:tagstring => params[:trace][:tagstring],
|
||||
:description => params[:trace][:description],
|
||||
:public => params[:trace][:public],
|
||||
:inserted => false, :user => @user,
|
||||
:timestamp => Time.now.getutc})
|
||||
@trace.valid?
|
||||
@trace.errors.add(:gpx_file, "can't be blank")
|
||||
end
|
||||
else
|
||||
@trace = Trace.new({:name => "Dummy",
|
||||
:tagstring => params[:trace][:tagstring],
|
||||
:description => params[:trace][:description],
|
||||
:public => params[:trace][:public],
|
||||
:inserted => false, :user => @user,
|
||||
:timestamp => Time.now})
|
||||
@trace.valid?
|
||||
@trace.errors.add(:gpx_file, "can't be blank")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -196,7 +204,7 @@ class TraceController < ApplicationController
|
|||
end
|
||||
|
||||
def georss
|
||||
conditions = ["gpx_files.public = 1"]
|
||||
conditions = ["gpx_files.public = ?", true]
|
||||
|
||||
if params[:display_name]
|
||||
conditions[0] += " AND users.display_name = ?"
|
||||
|
@ -278,12 +286,20 @@ class TraceController < ApplicationController
|
|||
|
||||
def api_create
|
||||
if request.post?
|
||||
do_create(params[:file], params[:tags], params[:description], params[:public])
|
||||
tags = params[:tags] || ""
|
||||
description = params[:description] || ""
|
||||
pub = params[:public] || false
|
||||
|
||||
if params[:file].respond_to?(:read)
|
||||
do_create(params[:file], tags, description, pub)
|
||||
|
||||
if @trace.id
|
||||
render :text => @trace.id.to_s, :content_type => "text/plain"
|
||||
elsif @trace.valid?
|
||||
render :nothing => true, :status => :internal_server_error
|
||||
if @trace.id
|
||||
render :text => @trace.id.to_s, :content_type => "text/plain"
|
||||
elsif @trace.valid?
|
||||
render :nothing => true, :status => :internal_server_error
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
|
@ -313,7 +329,7 @@ private
|
|||
:public => public,
|
||||
:inserted => true,
|
||||
:user => @user,
|
||||
:timestamp => Time.now
|
||||
:timestamp => Time.now.getutc
|
||||
})
|
||||
|
||||
# Save the trace object
|
||||
|
@ -328,6 +344,17 @@ private
|
|||
# Remove the file as we have failed to update the database
|
||||
FileUtils.rm_f(filename)
|
||||
end
|
||||
|
||||
# Finally save whether the user marked the trace as being public
|
||||
if @trace.public?
|
||||
if @user.trace_public_default.nil?
|
||||
@user.preferences.create(:k => "gps.trace.public", :v => "default")
|
||||
end
|
||||
else
|
||||
pref = @user.trace_public_default
|
||||
pref.destroy unless pref.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -83,7 +83,7 @@ class UserController < ApplicationController
|
|||
def lost_password
|
||||
@title = 'lost password'
|
||||
if params[:user] and params[:user][:email]
|
||||
user = User.find_by_email(params[:user][:email], :conditions => "visible = 1")
|
||||
user = User.find_by_email(params[:user][:email], :conditions => {:visible => true})
|
||||
|
||||
if user
|
||||
token = user.tokens.create
|
||||
|
@ -120,9 +120,21 @@ class UserController < ApplicationController
|
|||
|
||||
def new
|
||||
@title = 'create account'
|
||||
# The user is logged in already, so don't show them the signup page, instead
|
||||
# send them to the home page
|
||||
redirect_to :controller => 'site', :action => 'index' if session[:user]
|
||||
end
|
||||
|
||||
def login
|
||||
if session[:user]
|
||||
# The user is logged in already, if the referer param exists, redirect them to that
|
||||
if params[:referer]
|
||||
redirect_to params[:referer]
|
||||
else
|
||||
redirect_to :controller => 'site', :action => 'index'
|
||||
end
|
||||
return
|
||||
end
|
||||
@title = 'login'
|
||||
if params[:user]
|
||||
email_or_display_name = params[:user][:email]
|
||||
|
@ -223,7 +235,7 @@ class UserController < ApplicationController
|
|||
end
|
||||
|
||||
def view
|
||||
@this_user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1")
|
||||
@this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
|
||||
|
||||
if @this_user
|
||||
@title = @this_user.display_name
|
||||
|
@ -236,7 +248,7 @@ class UserController < ApplicationController
|
|||
def make_friend
|
||||
if params[:display_name]
|
||||
name = params[:display_name]
|
||||
new_friend = User.find_by_display_name(name, :conditions => "visible = 1")
|
||||
new_friend = User.find_by_display_name(name, :conditions => {:visible => true})
|
||||
friend = Friend.new
|
||||
friend.user_id = @user.id
|
||||
friend.friend_user_id = new_friend.id
|
||||
|
@ -258,7 +270,7 @@ class UserController < ApplicationController
|
|||
def remove_friend
|
||||
if params[:display_name]
|
||||
name = params[:display_name]
|
||||
friend = User.find_by_display_name(name, :conditions => "visible = 1")
|
||||
friend = User.find_by_display_name(name, :conditions => {:visible => true})
|
||||
if @user.is_friends_with?(friend)
|
||||
Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
|
||||
flash[:notice] = "#{friend.display_name} was removed from your friends."
|
||||
|
|
|
@ -5,11 +5,9 @@ class UserPreferenceController < ApplicationController
|
|||
def read_one
|
||||
pref = UserPreference.find(@user.id, params[:preference_key])
|
||||
|
||||
if pref
|
||||
render :text => pref.v.to_s
|
||||
else
|
||||
render :text => 'OH NOES! PREF NOT FOUND!', :status => 404
|
||||
end
|
||||
render :text => pref.v.to_s
|
||||
rescue ActiveRecord::RecordNotFound => ex
|
||||
render :text => 'OH NOES! PREF NOT FOUND!', :status => :not_found
|
||||
end
|
||||
|
||||
def update_one
|
||||
|
@ -32,6 +30,8 @@ class UserPreferenceController < ApplicationController
|
|||
UserPreference.delete(@user.id, params[:preference_key])
|
||||
|
||||
render :nothing => true
|
||||
rescue ActiveRecord::RecordNotFound => ex
|
||||
render :text => "param: #{params[:preference_key]} not found", :status => :not_found
|
||||
end
|
||||
|
||||
# print out all the preferences as a big xml block
|
||||
|
@ -54,46 +54,44 @@ class UserPreferenceController < ApplicationController
|
|||
def update
|
||||
begin
|
||||
p = XML::Parser.string(request.raw_post)
|
||||
doc = p.parse
|
||||
rescue LibXML::XML::Error, ArgumentError => ex
|
||||
raise OSM::APIBadXMLError.new("preferences", xml, ex.message)
|
||||
end
|
||||
doc = p.parse
|
||||
|
||||
prefs = []
|
||||
prefs = []
|
||||
|
||||
keyhash = {}
|
||||
keyhash = {}
|
||||
|
||||
doc.find('//preferences/preference').each do |pt|
|
||||
pref = UserPreference.new
|
||||
doc.find('//preferences/preference').each do |pt|
|
||||
pref = UserPreference.new
|
||||
|
||||
unless keyhash[pt['k']].nil? # already have that key
|
||||
render :text => 'OH NOES! CAN HAS UNIQUE KEYS?', :status => :not_acceptable
|
||||
return
|
||||
end
|
||||
|
||||
keyhash[pt['k']] = 1
|
||||
|
||||
pref.k = pt['k']
|
||||
pref.v = pt['v']
|
||||
pref.user_id = @user.id
|
||||
prefs << pref
|
||||
unless keyhash[pt['k']].nil? # already have that key
|
||||
render :text => 'OH NOES! CAN HAS UNIQUE KEYS?', :status => :not_acceptable
|
||||
end
|
||||
|
||||
if prefs.size > 150
|
||||
render :text => 'Too many preferences', :status => :request_entity_too_large
|
||||
return
|
||||
end
|
||||
keyhash[pt['k']] = 1
|
||||
|
||||
# kill the existing ones
|
||||
UserPreference.delete_all(['user_id = ?', @user.id])
|
||||
|
||||
# save the new ones
|
||||
prefs.each do |pref|
|
||||
pref.save!
|
||||
end
|
||||
|
||||
rescue Exception => ex
|
||||
render :text => 'OH NOES! FAIL!: ' + ex.to_s, :status => :internal_server_error
|
||||
return
|
||||
pref.k = pt['k']
|
||||
pref.v = pt['v']
|
||||
pref.user_id = @user.id
|
||||
prefs << pref
|
||||
end
|
||||
|
||||
if prefs.size > 150
|
||||
render :text => 'Too many preferences', :status => :request_entity_too_large
|
||||
end
|
||||
|
||||
# kill the existing ones
|
||||
UserPreference.delete_all(['user_id = ?', @user.id])
|
||||
|
||||
# save the new ones
|
||||
prefs.each do |pref|
|
||||
pref.save!
|
||||
end
|
||||
render :nothing => true
|
||||
|
||||
rescue Exception => ex
|
||||
render :text => 'OH NOES! FAIL!: ' + ex.to_s, :status => :internal_server_error
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,28 +3,28 @@ class WayController < ApplicationController
|
|||
|
||||
session :off
|
||||
before_filter :authorize, :only => [:create, :update, :delete]
|
||||
before_filter :require_public_data, :only => [:create, :update, :delete]
|
||||
before_filter :check_api_writable, :only => [:create, :update, :delete]
|
||||
before_filter :check_api_readable, :except => [:create, :update, :delete]
|
||||
after_filter :compress_output
|
||||
|
||||
def create
|
||||
if request.put?
|
||||
way = Way.from_xml(request.raw_post, true)
|
||||
|
||||
if way
|
||||
if !way.preconditions_ok?
|
||||
render :text => "", :status => :precondition_failed
|
||||
else
|
||||
way.user_id = @user.id
|
||||
way.save_with_history!
|
||||
begin
|
||||
if request.put?
|
||||
way = Way.from_xml(request.raw_post, true)
|
||||
|
||||
if way
|
||||
way.create_with_history @user
|
||||
render :text => way.id.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
end
|
||||
else
|
||||
render :nothing => true, :status => :method_not_allowed
|
||||
rescue OSM::APIError => ex
|
||||
logger.warn request.raw_post
|
||||
render ex.render_opts
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,6 +39,8 @@ class WayController < ApplicationController
|
|||
else
|
||||
render :text => "", :status => :gone
|
||||
end
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
|
@ -50,20 +52,14 @@ class WayController < ApplicationController
|
|||
new_way = Way.from_xml(request.raw_post)
|
||||
|
||||
if new_way and new_way.id == way.id
|
||||
if !new_way.preconditions_ok?
|
||||
render :text => "", :status => :precondition_failed
|
||||
else
|
||||
way.user_id = @user.id
|
||||
way.tags = new_way.tags
|
||||
way.nds = new_way.nds
|
||||
way.visible = true
|
||||
way.save_with_history!
|
||||
|
||||
render :nothing => true
|
||||
end
|
||||
way.update_from(new_way, @user)
|
||||
render :text => way.version.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
rescue OSM::APIError => ex
|
||||
logger.warn request.raw_post
|
||||
render ex.render_opts
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
|
@ -73,14 +69,16 @@ class WayController < ApplicationController
|
|||
def delete
|
||||
begin
|
||||
way = Way.find(params[:id])
|
||||
way.delete_with_relations_and_history(@user)
|
||||
new_way = Way.from_xml(request.raw_post)
|
||||
|
||||
# if we get here, all is fine, otherwise something will catch below.
|
||||
render :nothing => true
|
||||
rescue OSM::APIAlreadyDeletedError
|
||||
render :text => "", :status => :gone
|
||||
rescue OSM::APIPreconditionFailedError
|
||||
render :text => "", :status => :precondition_failed
|
||||
if new_way and new_way.id == way.id
|
||||
way.delete_with_history!(new_way, @user)
|
||||
render :text => way.version.to_s, :content_type => "text/plain"
|
||||
else
|
||||
render :nothing => true, :status => :bad_request
|
||||
end
|
||||
rescue OSM::APIError => ex
|
||||
render ex.render_opts
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
|
@ -92,7 +90,7 @@ class WayController < ApplicationController
|
|||
|
||||
if way.visible
|
||||
nd_ids = way.nds + [-1]
|
||||
nodes = Node.find(:all, :conditions => "visible = 1 AND id IN (#{nd_ids.join(',')})")
|
||||
nodes = Node.find(:all, :conditions => ["visible = ? AND id IN (#{nd_ids.join(',')})", true])
|
||||
|
||||
# Render
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
|
@ -130,13 +128,19 @@ class WayController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# returns all the ways which are currently using the node given in the
|
||||
# :id parameter. note that this used to return deleted ways as well, but
|
||||
# this seemed not to be the expected behaviour, so it was removed.
|
||||
def ways_for_node
|
||||
wayids = WayNode.find(:all, :conditions => ['node_id = ?', params[:id]]).collect { |ws| ws.id[0] }.uniq
|
||||
wayids = WayNode.find(:all,
|
||||
:conditions => ['node_id = ?', params[:id]]
|
||||
).collect { |ws| ws.id[0] }.uniq
|
||||
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
|
||||
Way.find(wayids).each do |way|
|
||||
doc.root << way.to_xml_node
|
||||
doc.root << way.to_xml_node if way.visible
|
||||
end
|
||||
|
||||
render :text => doc.to_s, :content_type => "text/xml"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue