can [:create, :update], :password
can :read, Redaction
can [:create, :destroy], :session
- can [:read, :data, :georss], Trace
+ can [:read, :data], Trace
can [:read, :create, :suspended, :auth_success, :auth_failure], User
can :read, UserBlock
end
authorize_resource
before_action :check_database_writable
- before_action :lookup_friend
+ before_action :lookup_user
def show
- @already_follows = current_user.follows?(@friend)
+ @already_follows = current_user.follows?(@user)
end
def create
follow = Follow.new
follow.follower = current_user
- follow.following = @friend
- if current_user.follows?(@friend)
- flash[:warning] = t ".already_followed", :name => @friend.display_name
+ follow.following = @user
+ if current_user.follows?(@user)
+ flash[:warning] = t ".already_followed", :name => @user.display_name
elsif current_user.follows.where(:created_at => Time.now.utc - 1.hour..).count >= current_user.max_follows_per_hour
flash[:error] = t ".limit_exceeded"
elsif follow.save
- flash[:notice] = t ".success", :name => @friend.display_name
+ flash[:notice] = t ".success", :name => @user.display_name
UserMailer.follow_notification(follow).deliver_later
else
- follow.add_error(t(".failed", :name => @friend.display_name))
+ follow.add_error(t(".failed", :name => @user.display_name))
end
referer = safe_referer(params[:referer]) if params[:referer]
end
def destroy
- if current_user.follows?(@friend)
- Follow.where(:follower => current_user, :following => @friend).delete_all
- flash[:notice] = t ".success", :name => @friend.display_name
+ if current_user.follows?(@user)
+ Follow.where(:follower => current_user, :following => @user).delete_all
+ flash[:notice] = t ".success", :name => @user.display_name
else
- flash[:error] = t ".not_followed", :name => @friend.display_name
+ flash[:error] = t ".not_followed", :name => @user.display_name
end
referer = safe_referer(params[:referer]) if params[:referer]
redirect_to referer || user_path
end
-
- private
-
- ##
- # ensure that there is a "friend" instance variable
- def lookup_friend
- @friend = User.active.find_by!(:display_name => params[:display_name])
- rescue ActiveRecord::RecordNotFound
- render_unknown_user params[:display_name]
- end
end
--- /dev/null
+module Traces
+ class FeedsController < ApplicationController
+ before_action :authorize_web
+ before_action :set_locale
+ before_action :check_database_readable
+
+ authorize_resource :class => Trace
+
+ def show
+ @traces = Trace.visible_to_all.visible
+
+ @traces = @traces.joins(:user).where(:users => { :display_name => params[:display_name] }) if params[:display_name]
+
+ @traces = @traces.tagged(params[:tag]) if params[:tag]
+ @traces = @traces.order("timestamp DESC")
+ @traces = @traces.limit(20)
+ @traces = @traces.includes(:user)
+ end
+ end
+end
include UserMethods
include PaginationMethods
- layout "site", :except => :georss
+ layout "site"
before_action :authorize_web
before_action :set_locale
head :not_found
end
- def georss
- @traces = Trace.visible_to_all.visible
-
- @traces = @traces.joins(:user).where(:users => { :display_name => params[:display_name] }) if params[:display_name]
-
- @traces = @traces.tagged(params[:tag]) if params[:tag]
- @traces = @traces.order("timestamp DESC")
- @traces = @traces.limit(20)
- @traces = @traces.includes(:user)
- end
-
private
def do_create(file, tags, description, visibility)
<% content_for :heading do %>
- <h1><%= t(@already_follows ? ".unfollow.heading" : ".follow.heading", :user => @friend.display_name) %></h1>
+ <h1><%= t(@already_follows ? ".unfollow.heading" : ".follow.heading", :user => @user.display_name) %></h1>
<% end %>
<%= bootstrap_form_tag :method => (@already_follows ? :delete : :post) do |f| %>
xml.channel do
xml.title t(".title")
xml.description t(".title")
- xml.link url_for(:controller => :traces, :action => :index, :only_path => false)
+ xml.link url_for(:controller => "/traces", :action => :index, :only_path => false)
xml.image do
xml.url image_url("mag_map-rss2.0.png")
xml.title t(".title")
xml.width 100
xml.height 100
- xml.link url_for(:controller => :traces, :action => :index, :only_path => false)
+ xml.link url_for(:controller => "/traces", :action => :index, :only_path => false)
end
@traces.each do |trace|
<div class="d-flex flex-column flex-md-row-reverse align-items-md-end">
<div class="pb-1 ps-1 d-flex flex-wrap flex-shrink-0 gap-1 justify-content-end">
- <%= link_to({ :action => :georss, :display_name => @target_user&.display_name, :tag => params[:tag] },
- { :class => "btn btn-secondary btn-sm" }) do %>
+ <%= link_to traces_feed_path(:display_name => @target_user&.display_name, :tag => params[:tag]),
+ :class => "btn btn-secondary btn-sm" do %>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" class="align-text-bottom">
<circle cx="2" cy="14" r="2" fill="white" />
<path d="M 8 14 a 6 6 0 0 0 -6 -6 M 14 14 a 12 12 0 0 0 -12 -12" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" />
<% end %>
<% content_for :auto_discovery_link_tag do %>
- <%= auto_discovery_link_tag :rss, :action => "georss", :display_name => @target_user&.display_name, :tag => params[:tag] %>
+ <%= auto_discovery_link_tag :rss, traces_feed_path(:display_name => @target_user&.display_name, :tag => params[:tag]) %>
<% end %>
<% if @traces.size > 0 %>
offline:
heading: "GPX Storage Offline"
message: "The GPX file storage and upload system is currently unavailable."
- georss:
- title: "OpenStreetMap GPS Traces"
- description:
- description_with_count:
- one: "GPX file with %{count} point from %{user}"
- other: "GPX file with %{count} points from %{user}"
- description_without_count: "GPX file from %{user}"
+ feeds:
+ show:
+ title: "OpenStreetMap GPS Traces"
+ description:
+ description_with_count:
+ one: "GPX file with %{count} point from %{user}"
+ other: "GPX file with %{count} points from %{user}"
+ description_without_count: "GPX file from %{user}"
application:
permission_denied: You do not have permission to access that action
require_cookies:
get "relations" => "relations#index"
get "map" => "map#index"
-
- get "trackpoints" => "tracepoints#index"
end
namespace :api, :path => "api/0.6" do
+ resources :tracepoints, :path => "trackpoints", :only => :index
+
resources :users, :only => :index
resources :users, :path => "user", :id => /\d+/, :only => :show
resources :user_traces, :path => "user/gpx_files", :module => :users, :controller => :traces, :only => :index
post "/preview/:type" => "site#preview", :as => :preview
# traces
- resources :traces, :except => [:show]
+ resources :traces, :id => /\d+/, :except => [:show]
get "/user/:display_name/traces/tag/:tag/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/user/%{display_name}/traces/tag/%{tag}")
get "/user/:display_name/traces/tag/:tag" => "traces#index"
get "/user/:display_name/traces/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/user/%{display_name}/traces")
get "/user/:display_name/traces" => "traces#index"
- get "/user/:display_name/traces/tag/:tag/rss" => "traces#georss", :defaults => { :format => :rss }
- get "/user/:display_name/traces/rss" => "traces#georss", :defaults => { :format => :rss }
- get "/user/:display_name/traces/:id" => "traces#show", :as => "show_trace"
- scope "/user/:display_name/traces/:trace_id", :module => :traces do
+ get "/user/:display_name/traces/:id" => "traces#show", :id => /\d+/, :as => "show_trace"
+ scope "/user/:display_name/traces/:trace_id", :module => :traces, :trace_id => /\d+/ do
get "picture" => "pictures#show", :as => "trace_picture"
get "icon" => "icons#show", :as => "trace_icon"
end
get "/traces/tag/:tag/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces/tag/%{tag}")
get "/traces/tag/:tag" => "traces#index"
get "/traces/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces")
- get "/traces/tag/:tag/rss" => "traces#georss", :defaults => { :format => :rss }
- get "/traces/rss" => "traces#georss", :defaults => { :format => :rss }
get "/traces/mine/tag/:tag/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces/mine/tag/%{tag}")
get "/traces/mine/tag/:tag" => "traces#mine"
get "/traces/mine/page/:page", :page => /[1-9][0-9]*/, :to => redirect(:path => "/traces/mine")
get "/traces/mine" => "traces#mine"
get "/trace/create", :to => redirect(:path => "/traces/new")
get "/trace/:id/data" => "traces#data", :id => /\d+/, :as => "trace_data"
- get "/trace/:id/edit", :to => redirect(:path => "/traces/%{id}/edit")
+ get "/trace/:id/edit", :id => /\d+/, :to => redirect(:path => "/traces/%{id}/edit")
+
+ namespace :traces, :path => "" do
+ resource :feed, :path => "(/user/:display_name)/traces(/tag/:tag)/rss", :only => :show, :defaults => { :format => :rss }
+ end
# diary pages
resources :diary_entries, :path => "diary", :only => [:new, :create, :index] do
maxlon = point.longitude + 0.001
maxlat = point.latitude + 0.001
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :success
assert_select "gpx[version='1.0'][creator='OpenStreetMap.org']", :count => 1 do
assert_select "trk" do
maxlon = point.longitude + 0.002
maxlat = point.latitude + 0.002
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :success
assert_select "gpx[version='1.0'][creator='OpenStreetMap.org']", :count => 1 do
assert_select "trk", :count => 1 do
maxlon = point.longitude + 0.002
maxlat = point.latitude + 0.002
bbox = "#{minlon},#{minlat},#{maxlon},#{maxlat}"
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :success
assert_select "gpx[version='1.0'][creator='OpenStreetMap.org']", :count => 1 do
assert_select "trk", :count => 1 do
end
def test_index_without_bbox
- get trackpoints_path
+ get api_tracepoints_path
assert_response :bad_request
assert_equal "The parameter bbox is required", @response.body, "A bbox param was expected"
end
def test_traces_page_less_than_zero
-10.upto(-1) do |i|
- get trackpoints_path(:page => i, :bbox => "-0.1,-0.1,0.1,0.1")
+ get api_tracepoints_path(:page => i, :bbox => "-0.1,-0.1,0.1,0.1")
assert_response :bad_request
assert_equal "Page number must be greater than or equal to 0", @response.body, "The page number was #{i}"
end
0.upto(10) do |i|
- get trackpoints_path(:page => i, :bbox => "-0.1,-0.1,0.1,0.1")
+ get api_tracepoints_path(:page => i, :bbox => "-0.1,-0.1,0.1,0.1")
assert_response :success, "The page number was #{i} and should have been accepted"
end
end
def test_bbox_too_big
@badbigbbox.each do |bbox|
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :bad_request, "The bbox:#{bbox} was expected to be too big"
assert_equal "The maximum bbox size is #{Settings.max_request_area}, and your request was too large. Either request a smaller area, or use planet.osm", @response.body, "bbox: #{bbox}"
end
def test_bbox_malformed
@badmalformedbbox.each do |bbox|
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :bad_request, "The bbox:#{bbox} was expected to be malformed"
assert_equal "The parameter bbox must be of the form min_lon,min_lat,max_lon,max_lat", @response.body, "bbox: #{bbox}"
end
def test_bbox_lon_mixedup
@badlonmixedbbox.each do |bbox|
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :bad_request, "The bbox:#{bbox} was expected to have the longitude mixed up"
assert_equal "The minimum longitude must be less than the maximum longitude, but it wasn't", @response.body, "bbox: #{bbox}"
end
def test_bbox_lat_mixedup
@badlatmixedbbox.each do |bbox|
- get trackpoints_path(:bbox => bbox)
+ get api_tracepoints_path(:bbox => bbox)
assert_response :bad_request, "The bbox:#{bbox} was expected to have the latitude mixed up"
assert_equal "The minimum latitude must be less than the maximum latitude, but it wasn't", @response.body, "bbox: #{bbox}"
end
def test_lat_lon_xml_format
create(:tracepoint, :latitude => (0.00004 * GeoRecord::SCALE).to_i, :longitude => (0.00008 * GeoRecord::SCALE).to_i)
- get trackpoints_path(:bbox => "0,0,0.1,0.1")
+ get api_tracepoints_path(:bbox => "0,0,0.1,0.1")
assert_match(/lat="0.0000400"/, response.body)
assert_match(/lon="0.0000800"/, response.body)
end
--- /dev/null
+require "test_helper"
+
+module Traces
+ class FeedsControllerTest < ActionDispatch::IntegrationTest
+ ##
+ # test all routes which lead to this controller
+ def test_routes
+ assert_routing(
+ { :path => "/traces/rss", :method => :get },
+ { :controller => "traces/feeds", :action => "show", :format => :rss }
+ )
+ assert_routing(
+ { :path => "/traces/tag/tagname/rss", :method => :get },
+ { :controller => "traces/feeds", :action => "show", :tag => "tagname", :format => :rss }
+ )
+ assert_routing(
+ { :path => "/user/username/traces/rss", :method => :get },
+ { :controller => "traces/feeds", :action => "show", :display_name => "username", :format => :rss }
+ )
+ assert_routing(
+ { :path => "/user/username/traces/tag/tagname/rss", :method => :get },
+ { :controller => "traces/feeds", :action => "show", :display_name => "username", :tag => "tagname", :format => :rss }
+ )
+ end
+
+ def test_show
+ user = create(:user)
+ # The fourth test below is surprisingly sensitive to timestamp ordering when the timestamps are equal.
+ trace_a = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago) do |trace|
+ create(:tracetag, :trace => trace, :tag => "London")
+ end
+ trace_b = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago) do |trace|
+ create(:tracetag, :trace => trace, :tag => "Birmingham")
+ end
+ create(:trace, :visibility => "private", :user => user, :timestamp => 2.seconds.ago) do |trace|
+ create(:tracetag, :trace => trace, :tag => "London")
+ end
+ create(:trace, :visibility => "private", :user => user, :timestamp => 1.second.ago) do |trace|
+ create(:tracetag, :trace => trace, :tag => "Birmingham")
+ end
+
+ # First with the public feed
+ get traces_feed_path
+ check_trace_feed [trace_b, trace_a]
+
+ # Restrict traces to those with a given tag
+ get traces_feed_path(:tag => "London")
+ check_trace_feed [trace_a]
+ end
+
+ def test_show_user
+ user = create(:user)
+ second_user = create(:user)
+ create(:user)
+ create(:trace)
+ trace_b = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago, :user => user)
+ trace_c = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago, :user => user) do |trace|
+ create(:tracetag, :trace => trace, :tag => "London")
+ end
+ create(:trace, :visibility => "private")
+
+ # Test a user with no traces
+ get traces_feed_path(:display_name => second_user)
+ check_trace_feed []
+
+ # Test the user with the traces - should see only public ones
+ get traces_feed_path(:display_name => user)
+ check_trace_feed [trace_c, trace_b]
+
+ # Should only see traces with the correct tag when a tag is specified
+ get traces_feed_path(:display_name => user, :tag => "London")
+ check_trace_feed [trace_c]
+
+ # Should no traces if the user does not exist
+ get traces_feed_path(:display_name => "UnknownUser")
+ check_trace_feed []
+ end
+
+ private
+
+ def check_trace_feed(traces)
+ assert_response :success
+ assert_template "traces/feeds/show"
+ assert_equal "application/rss+xml", @response.media_type
+ assert_select "rss", :count => 1 do
+ assert_select "channel", :count => 1 do
+ assert_select "title"
+ assert_select "description"
+ assert_select "link"
+ assert_select "image"
+ assert_select "item", :count => traces.length do |items|
+ traces.zip(items).each do |trace, item|
+ assert_select item, "title", trace.name
+ assert_select item, "link", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
+ assert_select item, "guid", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
+ assert_select item, "description" do
+ assert_dom_encoded do
+ assert_select "img[src='#{trace_icon_url trace.user, trace}']"
+ end
+ end
+ # assert_select item, "dc:creator", trace.user.display_name
+ assert_select item, "pubDate", trace.timestamp.rfc822
+ end
+ end
+ end
+ end
+ end
+ end
+end
{ :controller => "traces", :action => "mine", :tag => "tagname" }
)
- assert_routing(
- { :path => "/traces/rss", :method => :get },
- { :controller => "traces", :action => "georss", :format => :rss }
- )
- assert_routing(
- { :path => "/traces/tag/tagname/rss", :method => :get },
- { :controller => "traces", :action => "georss", :tag => "tagname", :format => :rss }
- )
- assert_routing(
- { :path => "/user/username/traces/rss", :method => :get },
- { :controller => "traces", :action => "georss", :display_name => "username", :format => :rss }
- )
- assert_routing(
- { :path => "/user/username/traces/tag/tagname/rss", :method => :get },
- { :controller => "traces", :action => "georss", :display_name => "username", :tag => "tagname", :format => :rss }
- )
-
assert_routing(
{ :path => "/user/username/traces/1", :method => :get },
{ :controller => "traces", :action => "show", :display_name => "username", :id => "1" }
end
end
- # Check the RSS feed
- def test_rss
- user = create(:user)
- # The fourth test below is surprisingly sensitive to timestamp ordering when the timestamps are equal.
- trace_a = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago) do |trace|
- create(:tracetag, :trace => trace, :tag => "London")
- end
- trace_b = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago) do |trace|
- create(:tracetag, :trace => trace, :tag => "Birmingham")
- end
- create(:trace, :visibility => "private", :user => user, :timestamp => 2.seconds.ago) do |trace|
- create(:tracetag, :trace => trace, :tag => "London")
- end
- create(:trace, :visibility => "private", :user => user, :timestamp => 1.second.ago) do |trace|
- create(:tracetag, :trace => trace, :tag => "Birmingham")
- end
-
- # First with the public feed
- get traces_rss_path
- check_trace_feed [trace_b, trace_a]
-
- # Restrict traces to those with a given tag
- get traces_rss_path(:tag => "London")
- check_trace_feed [trace_a]
- end
-
- # Check the RSS feed for a specific user
- def test_rss_user
- user = create(:user)
- second_user = create(:user)
- create(:user)
- create(:trace)
- trace_b = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago, :user => user)
- trace_c = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago, :user => user) do |trace|
- create(:tracetag, :trace => trace, :tag => "London")
- end
- create(:trace, :visibility => "private")
-
- # Test a user with no traces
- get traces_rss_path(:display_name => second_user.display_name)
- check_trace_feed []
-
- # Test the user with the traces - should see only public ones
- get traces_rss_path(:display_name => user.display_name)
- check_trace_feed [trace_c, trace_b]
-
- # Should only see traces with the correct tag when a tag is specified
- get traces_rss_path(:display_name => user.display_name, :tag => "London")
- check_trace_feed [trace_c]
-
- # Should no traces if the user does not exist
- get traces_rss_path(:display_name => "UnknownUser")
- check_trace_feed []
- end
-
# Test showing a trace
def test_show
public_trace_file = create(:trace, :visibility => "public")
private
- def check_trace_feed(traces)
- assert_response :success
- assert_template "georss"
- assert_equal "application/rss+xml", @response.media_type
- assert_select "rss", :count => 1 do
- assert_select "channel", :count => 1 do
- assert_select "title"
- assert_select "description"
- assert_select "link"
- assert_select "image"
- assert_select "item", :count => traces.length do |items|
- traces.zip(items).each do |trace, item|
- assert_select item, "title", trace.name
- assert_select item, "link", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
- assert_select item, "guid", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
- assert_select item, "description" do
- assert_dom_encoded do
- assert_select "img[src='#{trace_icon_url trace.user, trace}']"
- end
- end
- # assert_select item, "dc:creator", trace.user.display_name
- assert_select item, "pubDate", trace.timestamp.rfc822
- end
- end
- end
- end
- end
-
def check_trace_index(traces)
assert_response :success
assert_template "index"