Merge pull request #504 from knu/user_location_agent-issue-490

Update UserLocationAgent

Akinori MUSHA 10 年之前
父节点
当前提交
c35d6b99f0

+ 9 - 0
app/assets/javascripts/application.js.coffee.erb

@@ -215,3 +215,12 @@ $(document).ready ->
215 215
       showEventCreation()
216 216
     else
217 217
       hideEventCreation()
218
+
219
+  $('.selectable-text').each ->
220
+    $(this).click ->
221
+      range = document.createRange()
222
+      range.setStartBefore(this.firstChild)
223
+      range.setEndAfter(this.lastChild)
224
+      sel = window.getSelection()
225
+      sel.removeAllRanges();
226
+      sel.addRange(range)

+ 0 - 18
app/controllers/user_location_updates_controller.rb

@@ -1,18 +0,0 @@
1
-class UserLocationUpdatesController < ApplicationController
2
-  skip_before_filter :authenticate_user!
3
-
4
-  def create
5
-    user = User.find_by_id(params[:user_id])
6
-    if user
7
-      secret = params[:secret]
8
-      user.agents.of_type(Agents::UserLocationAgent).find_all {|agent| agent.options[:secret] == secret }.each do |agent|
9
-        agent.create_event :payload => params.except(:controller, :action, :secret, :user_id, :format),
10
-                           :lat => params[:latitude],
11
-                           :lng => params[:longitude]
12
-      end
13
-      render :text => "ok"
14
-    else
15
-      render :text => "user not found", :status => :not_found
16
-    end
17
-  end
18
-end

+ 15 - 0
app/controllers/web_requests_controller.rb

@@ -38,4 +38,19 @@ class WebRequestsController < ApplicationController
38 38
       render :text => "user not found", :status => 404
39 39
     end
40 40
   end
41
+
42
+  # legacy
43
+  def update_location
44
+    if user = User.find_by_id(params[:user_id])
45
+      secret = params[:secret]
46
+      user.agents.of_type(Agents::UserLocationAgent).each { |agent|
47
+        if agent.options[:secret] == secret
48
+          agent.trigger_web_request(params.except(:action, :controller, :user_id, :format), request.method_symbol.to_s, request.format.to_s)
49
+        end
50
+      }
51
+      render :text => "ok"
52
+    else
53
+      render :text => "user not found", :status => :not_found
54
+    end
55
+  end
41 56
 end

+ 31 - 2
app/models/agents/user_location_agent.rb

@@ -2,7 +2,6 @@ require 'securerandom'
2 2
 
3 3
 module Agents
4 4
   class UserLocationAgent < Agent
5
-    cannot_receive_events!
6 5
     cannot_be_scheduled!
7 6
 
8 7
     description do
@@ -40,5 +39,35 @@ module Agents
40 39
     def validate_options
41 40
       errors.add(:base, "secret is required and must be longer than 4 characters") unless options['secret'].present? && options['secret'].length > 4
42 41
     end
42
+
43
+    def receive(incoming_events)
44
+      incoming_events.each do |event|
45
+        interpolate_with(event) do
46
+          handle_payload event.payload
47
+        end
48
+      end
49
+    end
50
+
51
+    def receive_web_request(params, method, format)
52
+      params = params.symbolize_keys
53
+      if method != 'post'
54
+        return ['Not Found', 404]
55
+      end
56
+      if interpolated['secret'] != params[:secret]
57
+        return ['Not Authorized', 401]
58
+      end
59
+
60
+      handle_payload params.except(:secret)
61
+
62
+      return ['ok', 200]
63
+    end
64
+
65
+    private
66
+
67
+    def handle_payload(payload)
68
+      if payload[:latitude].present? && payload[:longitude].present?
69
+        create_event payload: payload, lat: payload[:latitude].to_f, lng: payload[:longitude].to_f
70
+      end
71
+    end
43 72
   end
44
-end
73
+end

+ 11 - 1
app/views/agents/agent_views/user_location_agent/_show.html.erb

@@ -17,10 +17,20 @@
17 17
   </script>
18 18
 
19 19
   <% events.each do |event| %>
20
-    <%= render "agents/agent_views/user_location_agent/map_marker", :event => event %>
20
+    <%= render "shared/map_marker", event: event %>
21 21
   <% end %>
22 22
 <% else %>
23 23
   <p>
24 24
     No events found.
25 25
   </p>
26 26
 <% end %>
27
+
28
+<h3>POST URL</h3>
29
+
30
+<p>
31
+  Location data containing <code>latitude</code> and <code>longitude</code> can be posted to this URL:<br/>
32
+
33
+  <ul>
34
+    <li><code class="selectable-text"><%= web_requests_url(user_id: @agent.user_id, agent_id: @agent.id, secret: @agent.options['secret']) %></code></li>
35
+  </ul>
36
+</p>

+ 1 - 1
app/views/events/show.html.erb

@@ -38,7 +38,7 @@
38 38
           var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
39 39
         </script>
40 40
 
41
-        <%= render "map_marker", :event => @event %>
41
+        <%= render "shared/map_marker", event: @event %>
42 42
       <% end %>
43 43
 
44 44
       <br />

app/views/agents/agent_views/user_location_agent/_map_marker.html.erb → app/views/shared/_map_marker.html.erb


+ 3 - 4
config/routes.rb

@@ -62,10 +62,9 @@ Huginn::Application.routes.draw do
62 62
 
63 63
   get "/worker_status" => "worker_status#show"
64 64
 
65
-  post "/users/:user_id/update_location/:secret" => "user_location_updates#create"
66
-
67
-  match  "/users/:user_id/web_requests/:agent_id/:secret" => "web_requests#handle_request", :as => :web_requests, :via => [:get, :post, :put, :delete]
68
-  post "/users/:user_id/webhooks/:agent_id/:secret" => "web_requests#handle_request" # legacy
65
+  match "/users/:user_id/web_requests/:agent_id/:secret" => "web_requests#handle_request", :as => :web_requests, :via => [:get, :post, :put, :delete]
66
+  post  "/users/:user_id/webhooks/:agent_id/:secret" => "web_requests#handle_request" # legacy
67
+  post  "/users/:user_id/update_location/:secret" => "web_requests#update_location" # legacy
69 68
 
70 69
   devise_for :users, :sign_out_via => [ :post, :delete ]
71 70
   get '/auth/:provider/callback', to: 'services#callback'

+ 0 - 39
spec/controllers/user_location_updates_controller_spec.rb

@@ -1,39 +0,0 @@
1
-require 'spec_helper'
2
-
3
-describe UserLocationUpdatesController do
4
-  before do
5
-    @agent = Agent.build_for_type("Agents::UserLocationAgent", users(:bob), :name => "something", :options => { :secret => "my_secret" })
6
-    @agent.save!
7
-  end
8
-
9
-  it "should create events without requiring login" do
10
-    post :create, :user_id => users(:bob).to_param, :secret => "my_secret", :longitude => 123, :latitude => 45, :something => "else"
11
-    @agent.events.last.payload.should == { 'longitude' => "123", 'latitude' => "45", 'something' => "else" }
12
-    @agent.events.last.lat.should == 45
13
-    @agent.events.last.lng.should == 123
14
-  end
15
-
16
-  it "should only consider Agents::UserLocationAgents for the given user" do
17
-    @jane_agent = Agent.build_for_type("Agents::UserLocationAgent", users(:jane), :name => "something", :options => { :secret => "my_secret" })
18
-    @jane_agent.save!
19
-
20
-    post :create, :user_id => users(:bob).to_param, :secret => "my_secret", :longitude => 123, :latitude => 45, :something => "else"
21
-    @agent.events.last.payload.should == { 'longitude' => "123", 'latitude' => "45", 'something' => "else" }
22
-    @jane_agent.events.should be_empty
23
-  end
24
-
25
-  it "should raise a 404 error when given an invalid user id" do
26
-    post :create, :user_id => "123", :secret => "not_my_secret", :longitude => 123, :latitude => 45, :something => "else"
27
-    response.should be_missing
28
-  end
29
-
30
-  it "should only look at agents with the given secret" do
31
-    @agent2 = Agent.build_for_type("Agents::UserLocationAgent", users(:bob), :name => "something", :options => { :secret => "my_secret2" })
32
-    @agent2.save!
33
-
34
-    lambda {
35
-      post :create, :user_id => users(:bob).to_param, :secret => "my_secret2", :longitude => 123, :latitude => 45, :something => "else"
36
-      @agent2.events.last.payload.should == { 'longitude' => "123", 'latitude' => "45", 'something' => "else" }
37
-    }.should_not change { @agent.events.count }
38
-  end
39
-end

+ 39 - 1
spec/controllers/web_requests_controller_spec.rb

@@ -94,4 +94,42 @@ describe WebRequestsController do
94 94
     post :handle_request, :user_id => users(:bob).to_param, :agent_id => 454545, :secret => "my_secret", :no => "go"
95 95
     response.should be_missing
96 96
   end
97
-end
97
+
98
+  describe "legacy update_location endpoint" do
99
+    before do
100
+      @agent = Agent.build_for_type("Agents::UserLocationAgent", users(:bob), name: "something", options: { secret: "my_secret" })
101
+      @agent.save!
102
+    end
103
+
104
+    it "should create events without requiring login" do
105
+      post :update_location, user_id: users(:bob).to_param, secret: "my_secret", longitude: 123, latitude: 45, something: "else"
106
+      @agent.events.last.payload.should == { 'longitude' => "123", 'latitude' => "45", 'something' => "else" }
107
+      @agent.events.last.lat.should == 45
108
+      @agent.events.last.lng.should == 123
109
+    end
110
+
111
+    it "should only consider Agents::UserLocationAgents for the given user" do
112
+      @jane_agent = Agent.build_for_type("Agents::UserLocationAgent", users(:jane), name: "something", options: { secret: "my_secret" })
113
+      @jane_agent.save!
114
+
115
+      post :update_location, user_id: users(:bob).to_param, secret: "my_secret", longitude: 123, latitude: 45, something: "else"
116
+      @agent.events.last.payload.should == { 'longitude' => "123", 'latitude' => "45", 'something' => "else" }
117
+      @jane_agent.events.should be_empty
118
+    end
119
+
120
+    it "should raise a 404 error when given an invalid user id" do
121
+      post :update_location, user_id: "123", secret: "not_my_secret", longitude: 123, latitude: 45, something: "else"
122
+      response.should be_missing
123
+    end
124
+
125
+    it "should only look at agents with the given secret" do
126
+      @agent2 = Agent.build_for_type("Agents::UserLocationAgent", users(:bob), name: "something", options: { secret: "my_secret2" })
127
+      @agent2.save!
128
+
129
+      lambda {
130
+        post :update_location, user_id: users(:bob).to_param, secret: "my_secret2", longitude: 123, latitude: 45, something: "else"
131
+        @agent2.events.last.payload.should == { 'longitude' => "123", 'latitude' => "45", 'something' => "else" }
132
+      }.should_not change { @agent.events.count }
133
+    end
134
+  end
135
+end

+ 48 - 0
spec/models/agents/user_location_agent_spec.rb

@@ -0,0 +1,48 @@
1
+require 'spec_helper'
2
+
3
+describe Agents::UserLocationAgent do
4
+  before do
5
+    @agent = Agent.build_for_type('Agents::UserLocationAgent', users(:bob), :name => 'something', :options => { :secret => 'my_secret' })
6
+    @agent.save!
7
+  end
8
+
9
+  it 'receives an event' do
10
+    event = Event.new
11
+    event.agent = agents(:bob_weather_agent)
12
+    event.created_at = Time.now
13
+    event.payload = { 'longitude' => 123, 'latitude' => 45, 'something' => 'else' }
14
+
15
+    lambda {
16
+      @agent.receive([event])
17
+    }.should change { @agent.events.count }.by(1)
18
+
19
+    @agent.events.last.payload.should == { 'longitude' => 123, 'latitude' => 45, 'something' => 'else' }
20
+    @agent.events.last.lat.should == 45
21
+    @agent.events.last.lng.should == 123
22
+  end
23
+
24
+  it 'does not accept a web request that is not POST' do
25
+    %w[get put delete patch].each { |method|
26
+      content, status, content_type = @agent.receive_web_request({ 'secret' => 'my_secret' }, method, 'application/json')
27
+      status.should == 404
28
+    }
29
+  end
30
+
31
+  it 'requires a valid secret for a web request' do
32
+    content, status, content_type = @agent.receive_web_request({ 'secret' => 'fake' }, 'post', 'application/json')
33
+    status.should == 401
34
+
35
+    content, status, content_type = @agent.receive_web_request({ 'secret' => 'my_secret' }, 'post', 'application/json')
36
+    status.should == 200
37
+  end
38
+
39
+  it 'creates an event on a web request' do
40
+    lambda {
41
+      @agent.receive_web_request({ 'secret' => 'my_secret', 'longitude' => 123, 'latitude' => 45, 'something' => 'else' }, 'post', 'application/json')
42
+    }.should change { @agent.events.count }.by(1)
43
+
44
+    @agent.events.last.payload.should == { 'longitude' => 123, 'latitude' => 45, 'something' => 'else' }
45
+    @agent.events.last.lat.should == 45
46
+    @agent.events.last.lng.should == 123
47
+  end
48
+end