From f720291b49862e2088433f081e3b935c32f81b38 Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Tue, 16 Sep 2014 19:38:32 +0900 Subject: [PATCH] UserLocationAgent: Receive events and accept POST via WebRequestsController. Show the POST URL on the details page while at it. The old user_location_updates URLs still work. This addresses #490. --- .../javascripts/application.js.coffee.erb | 9 ++++ .../user_location_updates_controller.rb | 4 +- app/models/agents/user_location_agent.rb | 33 ++++++++++++- .../user_location_agent/_show.html.erb | 10 ++++ config/routes.rb | 2 +- .../models/agents/user_location_agent_spec.rb | 48 +++++++++++++++++++ 6 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 spec/models/agents/user_location_agent_spec.rb diff --git a/app/assets/javascripts/application.js.coffee.erb b/app/assets/javascripts/application.js.coffee.erb index 87805c61..ad6e15c4 100644 --- a/app/assets/javascripts/application.js.coffee.erb +++ b/app/assets/javascripts/application.js.coffee.erb @@ -215,3 +215,12 @@ $(document).ready -> showEventCreation() else hideEventCreation() + + $('.selectable-text').each -> + $(this).click -> + range = document.createRange() + range.setStartBefore(this.firstChild) + range.setEndAfter(this.lastChild) + sel = window.getSelection() + sel.removeAllRanges(); + sel.addRange(range) diff --git a/app/controllers/user_location_updates_controller.rb b/app/controllers/user_location_updates_controller.rb index 6e60adeb..619449ad 100644 --- a/app/controllers/user_location_updates_controller.rb +++ b/app/controllers/user_location_updates_controller.rb @@ -6,9 +6,7 @@ class UserLocationUpdatesController < ApplicationController if user secret = params[:secret] user.agents.of_type(Agents::UserLocationAgent).find_all {|agent| agent.options[:secret] == secret }.each do |agent| - agent.create_event :payload => params.except(:controller, :action, :secret, :user_id, :format), - :lat => params[:latitude], - :lng => params[:longitude] + agent.trigger_web_request(params.except(:action, :controller, :user_id, :format), request.method_symbol.to_s, request.format.to_s) end render :text => "ok" else diff --git a/app/models/agents/user_location_agent.rb b/app/models/agents/user_location_agent.rb index e1b53ffd..2575e800 100644 --- a/app/models/agents/user_location_agent.rb +++ b/app/models/agents/user_location_agent.rb @@ -2,7 +2,6 @@ require 'securerandom' module Agents class UserLocationAgent < Agent - cannot_receive_events! cannot_be_scheduled! description do @@ -40,5 +39,35 @@ module Agents def validate_options errors.add(:base, "secret is required and must be longer than 4 characters") unless options['secret'].present? && options['secret'].length > 4 end + + def receive(incoming_events) + incoming_events.each do |event| + interpolate_with(event) do + handle_payload event.payload + end + end + end + + def receive_web_request(params, method, format) + params = params.symbolize_keys + if method != 'post' + return ['Not Found', 404] + end + if interpolated['secret'] != params[:secret] + return ['Not Authorized', 401] + end + + handle_payload params.except(:secret) + + return ['ok', 200] + end + + private + + def handle_payload(payload) + if payload[:latitude].present? && payload[:longitude].present? + create_event payload: payload, lat: payload[:latitude].to_f, lng: payload[:longitude].to_f + end + end end -end \ No newline at end of file +end diff --git a/app/views/agents/agent_views/user_location_agent/_show.html.erb b/app/views/agents/agent_views/user_location_agent/_show.html.erb index b0ca4faa..f1756ad8 100644 --- a/app/views/agents/agent_views/user_location_agent/_show.html.erb +++ b/app/views/agents/agent_views/user_location_agent/_show.html.erb @@ -24,3 +24,13 @@ No events found.

<% end %> + +

POST URL

+ +

+ Location data containing latitude and longitude can be posted to this URL:
+ +

+

diff --git a/config/routes.rb b/config/routes.rb index 67e5a4ff..3048aa5f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -62,7 +62,7 @@ Huginn::Application.routes.draw do get "/worker_status" => "worker_status#show" - post "/users/:user_id/update_location/:secret" => "user_location_updates#create" + post "/users/:user_id/update_location/:secret" => "user_location_updates#create" # legacy match "/users/:user_id/web_requests/:agent_id/:secret" => "web_requests#handle_request", :as => :web_requests, :via => [:get, :post, :put, :delete] post "/users/:user_id/webhooks/:agent_id/:secret" => "web_requests#handle_request" # legacy diff --git a/spec/models/agents/user_location_agent_spec.rb b/spec/models/agents/user_location_agent_spec.rb new file mode 100644 index 00000000..0cf8fd6e --- /dev/null +++ b/spec/models/agents/user_location_agent_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe Agents::UserLocationAgent do + before do + @agent = Agent.build_for_type('Agents::UserLocationAgent', users(:bob), :name => 'something', :options => { :secret => 'my_secret' }) + @agent.save! + end + + it 'receives an event' do + event = Event.new + event.agent = agents(:bob_weather_agent) + event.created_at = Time.now + event.payload = { 'longitude' => 123, 'latitude' => 45, 'something' => 'else' } + + lambda { + @agent.receive([event]) + }.should change { @agent.events.count }.by(1) + + @agent.events.last.payload.should == { 'longitude' => 123, 'latitude' => 45, 'something' => 'else' } + @agent.events.last.lat.should == 45 + @agent.events.last.lng.should == 123 + end + + it 'does not accept a web request that is not POST' do + %w[get put delete patch].each { |method| + content, status, content_type = @agent.receive_web_request({ 'secret' => 'my_secret' }, method, 'application/json') + status.should == 404 + } + end + + it 'requires a valid secret for a web request' do + content, status, content_type = @agent.receive_web_request({ 'secret' => 'fake' }, 'post', 'application/json') + status.should == 401 + + content, status, content_type = @agent.receive_web_request({ 'secret' => 'my_secret' }, 'post', 'application/json') + status.should == 200 + end + + it 'creates an event on a web request' do + lambda { + @agent.receive_web_request({ 'secret' => 'my_secret', 'longitude' => 123, 'latitude' => 45, 'something' => 'else' }, 'post', 'application/json') + }.should change { @agent.events.count }.by(1) + + @agent.events.last.payload.should == { 'longitude' => 123, 'latitude' => 45, 'something' => 'else' } + @agent.events.last.lat.should == 45 + @agent.events.last.lng.should == 123 + end +end