From 4c44df5fdf01c6d4f758c997b7f402fb512af4ca Mon Sep 17 00:00:00 2001 From: Harel M Date: Mon, 21 Apr 2025 20:04:56 +0000 Subject: [PATCH] Add support for JSON traces API Co-authored-by: Tom Hughes Co-authored-by: Marwin Hochfelsner <50826859+hlfan@users.noreply.github.com> --- app/controllers/api/traces_controller.rb | 8 +++++++- app/controllers/api/users/traces_controller.rb | 6 +++++- app/views/api/traces/_trace.json.jbuilder | 15 +++++++++++++++ app/views/api/traces/show.json.jbuilder | 5 +++++ app/views/api/users/traces/index.json.jbuilder | 5 +++++ test/controllers/api/traces_controller_test.rb | 16 +++++++++++++++- .../api/users/traces_controller_test.rb | 16 ++++++++++++++++ 7 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 app/views/api/traces/_trace.json.jbuilder create mode 100644 app/views/api/traces/show.json.jbuilder create mode 100644 app/views/api/users/traces/index.json.jbuilder diff --git a/app/controllers/api/traces_controller.rb b/app/controllers/api/traces_controller.rb index e91261058..00540a120 100644 --- a/app/controllers/api/traces_controller.rb +++ b/app/controllers/api/traces_controller.rb @@ -1,6 +1,7 @@ module Api class TracesController < ApiController before_action :check_api_writable, :only => [:create, :update, :destroy] + before_action :set_request_formats, :only => [:show] before_action :set_locale before_action :authorize @@ -12,7 +13,12 @@ module Api def show @trace = Trace.visible.find(params[:id]) - head :forbidden unless @trace.public? || @trace.user == current_user + return head :forbidden unless @trace.public? || @trace.user == current_user + + respond_to do |format| + format.xml + format.json + end end def create diff --git a/app/controllers/api/users/traces_controller.rb b/app/controllers/api/users/traces_controller.rb index 379515d49..769aca34d 100644 --- a/app/controllers/api/users/traces_controller.rb +++ b/app/controllers/api/users/traces_controller.rb @@ -2,12 +2,16 @@ module Api module Users class TracesController < ApiController before_action :authorize + before_action :set_request_formats authorize_resource :trace def index @traces = current_user.traces.reload - render :content_type => "application/xml" + respond_to do |format| + format.xml + format.json + end end end end diff --git a/app/views/api/traces/_trace.json.jbuilder b/app/views/api/traces/_trace.json.jbuilder new file mode 100644 index 000000000..6d84ce4b8 --- /dev/null +++ b/app/views/api/traces/_trace.json.jbuilder @@ -0,0 +1,15 @@ +json.id trace.id +json.name trace.name +json.uid trace.user_id +json.user trace.user.display_name +json.visibility trace.visibility +json.pending !trace.inserted +json.timestamp trace.timestamp.xmlschema + +if trace.inserted + json.lat trace.latitude + json.lon trace.longitude +end + +json.description trace.description +json.tags trace.tags.map(&:tag) diff --git a/app/views/api/traces/show.json.jbuilder b/app/views/api/traces/show.json.jbuilder new file mode 100644 index 000000000..f750a2f85 --- /dev/null +++ b/app/views/api/traces/show.json.jbuilder @@ -0,0 +1,5 @@ +json.partial! "api/root_attributes" + +json.trace do + json.partial! "api/traces/trace", :trace => @trace +end diff --git a/app/views/api/users/traces/index.json.jbuilder b/app/views/api/users/traces/index.json.jbuilder new file mode 100644 index 000000000..0d9c12a1c --- /dev/null +++ b/app/views/api/users/traces/index.json.jbuilder @@ -0,0 +1,5 @@ +json.partial! "api/root_attributes" + +json.traces @traces do |trace| + json.partial! "api/traces/trace", :trace => trace +end diff --git a/test/controllers/api/traces_controller_test.rb b/test/controllers/api/traces_controller_test.rb index 367bb6d21..ecb92d03b 100644 --- a/test/controllers/api/traces_controller_test.rb +++ b/test/controllers/api/traces_controller_test.rb @@ -17,6 +17,10 @@ module Api { :path => "/api/0.6/gpx/1", :method => :get }, { :controller => "api/traces", :action => "show", :id => "1" } ) + assert_routing( + { :path => "/api/0.6/gpx/1.json", :method => :get }, + { :controller => "api/traces", :action => "show", :id => "1", :format => "json" } + ) assert_routing( { :path => "/api/0.6/gpx/1", :method => :put }, { :controller => "api/traces", :action => "update", :id => "1" } @@ -44,11 +48,21 @@ module Api get api_trace_path(public_trace_file), :headers => auth_header assert_response :success - # And finally we should be able to do it with the owner of the trace + # We should be able to do it with the owner of the trace auth_header = bearer_authorization_header public_trace_file.user get api_trace_path(public_trace_file), :headers => auth_header assert_response :success assert_select "gpx_file[id='#{public_trace_file.id}'][uid='#{public_trace_file.user.id}']", 1 + + # We should be able to do it with the owner of the trace with json format + auth_header = bearer_authorization_header public_trace_file.user + get api_trace_path(public_trace_file, :format => "json"), :headers => auth_header + assert_response :success + assert_equal "application/json", response.media_type + js = ActiveSupport::JSON.decode(@response.body) + assert_not_nil js + assert_equal public_trace_file.id, js["trace"]["id"] + assert_equal public_trace_file.user.id, js["trace"]["uid"] end # Check an anonymous trace can't be specifically fetched by another user diff --git a/test/controllers/api/users/traces_controller_test.rb b/test/controllers/api/users/traces_controller_test.rb index 2f464056f..0123cd3f2 100644 --- a/test/controllers/api/users/traces_controller_test.rb +++ b/test/controllers/api/users/traces_controller_test.rb @@ -10,6 +10,10 @@ module Api { :path => "/api/0.6/user/gpx_files", :method => :get }, { :controller => "api/users/traces", :action => "index" } ) + assert_routing( + { :path => "/api/0.6/user/gpx_files.json", :method => :get }, + { :controller => "api/users/traces", :action => "index", :format => "json" } + ) end def test_index @@ -34,6 +38,18 @@ module Api assert_select "gpx_file[id='#{trace2.id}']", 1 do assert_select "tag", "Birmingham" end + + # check that we get a response when logged in with json + auth_header = bearer_authorization_header user, :scopes => %w[read_gpx] + get api_user_traces_path(:format => "json"), :headers => auth_header + assert_response :success + assert_equal "application/json", response.media_type + js = ActiveSupport::JSON.decode(@response.body) + assert_not_nil js + assert_equal trace1.id, js["traces"][0]["id"] + assert_equal "London", js["traces"][0]["tags"][0] + assert_equal trace2.id, js["traces"][1]["id"] + assert_equal "Birmingham", js["traces"][1]["tags"][0] end def test_index_anonymous -- 2.39.5