Add extra visibility options for GPS traces, and enhance the API call

that returns trace data to return more information if the owner of the
trace has allowed it. Based on a patch from Matt Amos.
This commit is contained in:
Tom Hughes 2009-08-13 17:06:11 +00:00
parent 7a7c567436
commit 565171486f
16 changed files with 252 additions and 81 deletions

View file

@ -11,10 +11,7 @@ class ApiController < ApplicationController
# within the specified bounding box, and in the specified page.
def trackpoints
#retrieve the page number
page = params['page'].to_i
unless page
page = 0;
end
page = params['page'].to_s.to_i
unless page >= 0
report_error("Page number must be greater than or equal to 0")
@ -42,7 +39,7 @@ class ApiController < ApplicationController
end
# get all the points
points = Tracepoint.find_by_area(min_lat, min_lon, max_lat, max_lon, :offset => offset, :limit => APP_CONFIG['tracepoints_per_page'], :order => "timestamp DESC" )
points = Tracepoint.find_by_area(min_lat, min_lon, max_lat, max_lon, :offset => offset, :limit => APP_CONFIG['tracepoints_per_page'], :order => "gpx_id DESC, trackid ASC, timestamp ASC" )
doc = XML::Document.new
doc.encoding = XML::Encoding::UTF_8
@ -53,14 +50,61 @@ class ApiController < ApplicationController
doc.root = root
track = XML::Node.new 'trk'
doc.root << track
trkseg = XML::Node.new 'trkseg'
track << trkseg
# initialise these variables outside of the loop so that they
# stay in scope and don't get free'd up by the GC during the
# loop.
gpx_id = -1
trackid = -1
track = nil
trkseg = nil
anon_track = nil
anon_trkseg = nil
gpx_file = nil
timestamps = false
points.each do |point|
trkseg << point.to_xml_node()
if gpx_id != point.gpx_id
gpx_id = point.gpx_id
trackid = -1
gpx_file = Trace.find(gpx_id)
if gpx_file.trackable?
track = XML::Node.new 'trk'
doc.root << track
timestamps = true
if gpx_file.identifiable?
track << (XML::Node.new("name") << gpx_file.name)
track << (XML::Node.new("desc") << gpx_file.description)
track << (XML::Node.new("url") << url_for(:controller => 'trace', :action => 'view', :id => gpx_file.id))
end
else
# use the anonymous track segment if the user hasn't allowed
# their GPX points to be tracked.
timestamps = false
if anon_track.nil?
anon_track = XML::Node.new 'trk'
doc.root << anon_track
end
track = anon_track
end
end
if trackid != point.trackid
if gpx_file.trackable?
trkseg = XML::Node.new 'trkseg'
track << trkseg
trackid = point.trackid
else
if anon_trkseg.nil?
anon_trkseg = XML::Node.new 'trkseg'
anon_track << anon_trkseg
end
trkseg = anon_trkseg
end
end
trkseg << point.to_xml_node(timestamps)
end
response.headers["Content-Disposition"] = "attachment; filename=\"map.osm\""

View file

@ -3,10 +3,10 @@ class TraceController < ApplicationController
before_filter :authorize_web
before_filter :set_locale
before_filter :require_user, :only => [:mine, :create, :edit, :delete, :make_public]
before_filter :require_user, :only => [:mine, :create, :edit, :delete]
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]
before_filter :check_database_writable, :only => [:create, :edit, :delete]
before_filter :check_api_readable, :only => [:api_details, :api_data]
before_filter :check_api_writable, :only => [:api_create]
@ -43,15 +43,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 = ? OR gpx_files.user_id = ?)", true, @user.id] #1
conditions = ["(gpx_files.visibility <> 'private' OR gpx_files.user_id = ?)", @user.id] #1
else
conditions = ["gpx_files.public = ?", true] #2
conditions = ["gpx_files.visibility <> 'private'"] #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 = ? AND gpx_files.user_id = ?", true, target_user.id] #4
conditions = ["gpx_files.public <> 'private' AND gpx_files.user_id = ?", target_user.id] #4
end
end
@ -96,10 +96,13 @@ class TraceController < ApplicationController
def mine
# Load the preference of whether the user set the trace public the last time
@trace = Trace.new
if @user.preferences.find(:first, :conditions => {:k => "gps.trace.public", :v => "default"}).nil?
@trace.public = false
visibility = @user.preferences.find(:first, :conditions => {:k => "gps.trace.visibility"})
if visibility
@trace.visibility = visibility.v
elsif @user.preferences.find(:first, :conditions => {:k => "gps.trace.public", :v => "default"}).nil?
@trace.visibility = "private"
else
@trace.public = true
@trace.visibility = "public"
end
list(@user, "mine")
end
@ -124,7 +127,7 @@ class TraceController < ApplicationController
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])
params[:trace][:description], params[:trace][:visibility])
if @trace.id
logger.info("id is #{@trace.id}")
@ -136,7 +139,7 @@ class TraceController < ApplicationController
@trace = Trace.new({:name => "Dummy",
:tagstring => params[:trace][:tagstring],
:description => params[:trace][:description],
:public => params[:trace][:public],
:visibility => params[:trace][:visibility],
:inserted => false, :user => @user,
:timestamp => Time.now.getutc})
@trace.valid?
@ -170,6 +173,7 @@ class TraceController < ApplicationController
if params[:trace]
@trace.description = params[:trace][:description]
@trace.tagstring = params[:trace][:tagstring]
@trace.visibility = params[:trace][:visibility]
if @trace.save
redirect_to :action => 'view'
end
@ -200,27 +204,8 @@ class TraceController < ApplicationController
render :nothing => true, :status => :not_found
end
def make_public
trace = Trace.find(params[:id])
if @user and trace.user == @user
if request.post? and !trace.public?
trace.public = true
trace.save
flash[:notice] = t 'trace.make_public.made_public'
redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
else
render :nothing => true, :status => :bad_request
end
else
render :nothing => true, :status => :forbidden
end
rescue ActiveRecord::RecordNotFound
render :nothing => true, :status => :not_found
end
def georss
conditions = ["gpx_files.public = ?", true]
conditions = ["gpx_files.visibility <> 'private'"]
if params[:display_name]
conditions[0] += " AND users.display_name = ?"
@ -249,7 +234,7 @@ class TraceController < ApplicationController
if trace.inserted?
if trace.public? or (@user and @user == trace.user)
expires_in 7.days, :private => !trace.public, :public => trace.public
expires_in 7.days, :private => !trace.public?, :public => trace.public?
send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
else
render :nothing => true, :status => :forbidden
@ -266,7 +251,7 @@ class TraceController < ApplicationController
if trace.inserted?
if trace.public? or (@user and @user == trace.user)
expires_in 7.days, :private => !trace.public, :public => trace.public
expires_in 7.days, :private => !trace.public?, :public => trace.public?
send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
else
render :nothing => true, :status => :forbidden
@ -306,10 +291,14 @@ class TraceController < ApplicationController
if request.post?
tags = params[:tags] || ""
description = params[:description] || ""
pub = params[:public] || false
visibility = params[:visibility] || false
if params[:public] && !visibility
visibility = "public"
end
if params[:file].respond_to?(:read)
do_create(params[:file], tags, description, pub)
do_create(params[:file], tags, description, visibility)
if @trace.id
render :text => @trace.id.to_s, :content_type => "text/plain"
@ -328,7 +317,7 @@ class TraceController < ApplicationController
private
def do_create(file, tags, description, public)
def do_create(file, tags, description, visibility)
# Sanitise the user's filename
name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
@ -344,7 +333,7 @@ private
:name => name,
:tagstring => tags,
:description => description,
:public => public,
:visibility => visibility,
:inserted => true,
:user => @user,
:timestamp => Time.now.getutc
@ -363,14 +352,12 @@ private
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
# Finally save the user's preferred previacy level
if pref = @user.preferences.find(:first, :conditions => {:k => "gps.trace.visibility"})
pref.v = visibility
pref.save
else
pref = @user.trace_public_default
pref.destroy unless pref.nil?
@user.preferences.create(:k => "gps.trace.visibility", :v => visibility)
end
end