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.
This commit is contained in:
Akinori MUSHA 2014-09-16 19:38:32 +09:00
parent 0f2af0ac12
commit f720291b49
6 changed files with 100 additions and 6 deletions

View file

@ -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)

View file

@ -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

View file

@ -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
end

View file

@ -24,3 +24,13 @@
No events found.
</p>
<% end %>
<h3>POST URL</h3>
<p>
Location data containing <code>latitude</code> and <code>longitude</code> can be posted to this URL:<br/>
<ul>
<li><code class="selectable-text"><%= web_requests_url(user_id: @agent.user_id, agent_id: @agent.id, secret: @agent.options['secret']) %></code></li>
</ul>
</p>

View file

@ -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

View file

@ -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