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:
+
+
+ <%= web_requests_url(user_id: @agent.user_id, agent_id: @agent.id, secret: @agent.options['secret']) %>
+
+
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