garufa 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/garufa.gemspec +2 -1
- data/lib/garufa/api/authentication.rb +12 -11
- data/lib/garufa/api/body_reader.rb +7 -7
- data/lib/garufa/api/event_handler.rb +10 -12
- data/lib/garufa/api/filter.rb +12 -0
- data/lib/garufa/api/routes/channels.rb +19 -16
- data/lib/garufa/api/routes/events.rb +13 -15
- data/lib/garufa/api/server.rb +25 -15
- data/lib/garufa/api/stats.rb +47 -0
- data/lib/garufa/subscriptions.rb +17 -38
- data/lib/garufa/version.rb +1 -1
- data/test/api.rb +171 -0
- data/test/connection.rb +3 -1
- data/test/helper.rb +41 -5
- metadata +22 -13
- data/bin/garufa.pid +0 -1
- data/lib/garufa/api/channel_filter.rb +0 -12
- data/lib/garufa/api/channel_stats.rb +0 -18
- data/lib/garufa/api/channels.rb +0 -31
- data/lib/garufa/api/events.rb +0 -15
- data/lib/garufa/api/response_writer.rb +0 -9
- data/lib/garufa/api/settings_setter.rb +0 -15
- data/lib/garufa/api/terminal_matcher.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22a0ca00cbf5a46859528cb7d432de18fd51415e
|
4
|
+
data.tar.gz: 4b78467ab0979477e6c72dd113da8e1ff06dd1ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a994bc4b5497f5d286765b591119ff93739f57f8aebb186c6f0655ced8fa561538d043d8a97088bf6100f6bbf6520a44d05ec07a1cc0f5f0df74530ca0208281
|
7
|
+
data.tar.gz: b5a43947171fe24cf4e84a1c7176dc55f4f674ce6e7730f8f98a8363643dcf9199474cdaa9b2bf039ac0545e12682d38e40761ae6047547895d247e817a36d16
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
[](https://travis-ci.org/Juanmcuello/garufa)
|
2
2
|
[](https://codeclimate.com/github/Juanmcuello/garufa)
|
3
3
|
|
4
|
+

|
5
|
+
|
4
6
|
Garufa
|
5
7
|
====
|
6
8
|
|
data/garufa.gemspec
CHANGED
@@ -29,10 +29,11 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_dependency "goliath", "1.0.4"
|
30
30
|
s.add_dependency "faye-websocket", "0.7.4"
|
31
31
|
s.add_dependency "websocket-driver", "0.3.5"
|
32
|
-
s.add_dependency "
|
32
|
+
s.add_dependency "roda", "2.4.0"
|
33
33
|
s.add_dependency "signature", "0.1.7"
|
34
34
|
s.add_dependency "tilt", "2.0.1"
|
35
35
|
s.add_dependency "yajl-ruby", "1.2.1"
|
36
|
+
s.add_development_dependency "rack-test", "0.6.3"
|
36
37
|
s.add_development_dependency "rake", "10.3.2"
|
37
38
|
s.add_development_dependency "minitest", "5.4.0"
|
38
39
|
end
|
@@ -1,19 +1,20 @@
|
|
1
1
|
require 'signature'
|
2
2
|
require 'garufa/config'
|
3
3
|
|
4
|
-
module
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
request.authenticate { |key| Signature::Token.new(key, Garufa::Config[:secret]) }
|
4
|
+
module Authentication
|
5
|
+
module InstanceMethods
|
6
|
+
def authenticate(app_id)
|
7
|
+
r = Signature::Request.new(request.request_method, request.path, request.params)
|
8
|
+
r.authenticate { |key| Signature::Token.new(key, Garufa::Config[:secret]) }
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
rescue Signature::AuthenticationError
|
15
|
-
halt([401, {}, ['401 Unauthorized']])
|
10
|
+
if app_id != Garufa::Config[:app_id]
|
11
|
+
request.halt [400, {}, ["Token validated, but invalid for app #{app_id}"]]
|
16
12
|
end
|
13
|
+
|
14
|
+
rescue Signature::AuthenticationError
|
15
|
+
request.halt [401, {}, ['401 Unauthorized']]
|
17
16
|
end
|
18
17
|
end
|
19
18
|
end
|
19
|
+
|
20
|
+
Roda.plugin Authentication
|
@@ -1,10 +1,10 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
body
|
7
|
-
end
|
1
|
+
module BodyReader
|
2
|
+
module InstanceMethods
|
3
|
+
def read_body
|
4
|
+
body = request.body.read; request.body.rewind
|
5
|
+
body
|
8
6
|
end
|
9
7
|
end
|
10
8
|
end
|
9
|
+
|
10
|
+
Roda.plugin BodyReader
|
@@ -5,26 +5,24 @@ require 'garufa/message'
|
|
5
5
|
|
6
6
|
module Garufa
|
7
7
|
module API
|
8
|
-
|
9
|
-
def handle_events(body, channel = nil, params = {})
|
8
|
+
class EventHandler
|
10
9
|
|
11
|
-
|
10
|
+
def handle(body)
|
11
|
+
notify JSON.parse(body)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
+
def handle_legacy(body, channel, params)
|
15
|
+
notify params.merge(channels: [channel], data: JSON.parse(body))
|
16
|
+
end
|
14
17
|
|
15
|
-
|
16
|
-
# in the body. New clients send everything in the body. We have to check where
|
17
|
-
# data is coming in to build the final params.
|
18
|
-
params.merge!(body_params['data'] ? body_params : { data: body_params })
|
18
|
+
private
|
19
19
|
|
20
|
+
def notify(params)
|
20
21
|
message = Garufa::Message.new(params)
|
21
22
|
options = { data: message.data, socket_id: message.socket_id }
|
22
23
|
|
23
|
-
#
|
24
|
+
# Notify event deferred in order to response immediately.
|
24
25
|
EM.defer { Garufa::Subscriptions.notify message.channels, message.name, options }
|
25
|
-
|
26
|
-
rescue JSON::ParserError => e
|
27
|
-
env.logger.error e.inspect
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
@@ -2,31 +2,34 @@ module Garufa
|
|
2
2
|
module API
|
3
3
|
module Routes
|
4
4
|
module Channels
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
Server.route('channels') do |r|
|
6
|
+
r.on 'channels' do
|
7
|
+
|
8
|
+
stats = Stats.new(Subscriptions.all)
|
9
|
+
|
10
|
+
# GET channels
|
11
|
+
r.is do
|
12
|
+
render 'channels', locals: { stats: stats.all_channels, filter: filter }
|
10
13
|
end
|
11
14
|
|
12
|
-
# GET channels/presence-channel
|
13
|
-
|
14
|
-
|
15
|
+
# GET channels/presence-channel
|
16
|
+
r.is "presence-:channel" do |channel|
|
17
|
+
render 'presence', locals: { stats: stats.single_channel(channel), filter: filter }
|
15
18
|
end
|
16
19
|
|
17
|
-
# GET channels/
|
18
|
-
|
19
|
-
|
20
|
+
# GET channels/presence-channel/users
|
21
|
+
r.is /(presence-.+)\/users/ do |channel|
|
22
|
+
render 'presence_users', locals: { stats: stats.single_channel(channel) }
|
20
23
|
end
|
21
24
|
|
22
25
|
# GET channels/non-presence-channel
|
23
|
-
|
24
|
-
|
26
|
+
r.is ":channel" do |channel|
|
27
|
+
render 'non_presence', locals: { stats: stats.single_channel(channel) }
|
25
28
|
end
|
26
29
|
|
27
|
-
# GET channels
|
28
|
-
|
29
|
-
|
30
|
+
# GET channels/non-presence-channel/users
|
31
|
+
r.is ":channel/users" do |channel|
|
32
|
+
response.status = 400
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
@@ -2,22 +2,20 @@ module Garufa
|
|
2
2
|
module API
|
3
3
|
module Routes
|
4
4
|
module Events
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
res.write '{}'
|
13
|
-
end
|
5
|
+
Server.route('events') do |r|
|
6
|
+
r.is 'events' do
|
7
|
+
handler = EventHandler.new
|
8
|
+
handler.handle(read_body)
|
9
|
+
response.status = 202
|
10
|
+
'{}'
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
# Legacy events
|
14
|
+
r.is 'channels/:channel/events' do |channel|
|
15
|
+
handler = EventHandler.new
|
16
|
+
handler.handle_legacy(read_body, channel, request.GET)
|
17
|
+
response.status = 202
|
18
|
+
'{}'
|
21
19
|
end
|
22
20
|
end
|
23
21
|
end
|
data/lib/garufa/api/server.rb
CHANGED
@@ -1,27 +1,37 @@
|
|
1
|
-
require '
|
1
|
+
require 'roda'
|
2
|
+
require 'yajl'
|
3
|
+
require 'yajl/json_gem'
|
4
|
+
require 'tilt/yajl'
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
+
require_relative '../subscriptions'
|
7
|
+
require_relative 'stats'
|
8
|
+
require_relative 'filter'
|
9
|
+
require_relative 'authentication'
|
10
|
+
require_relative 'body_reader'
|
11
|
+
require_relative 'event_handler'
|
6
12
|
|
7
13
|
module Garufa
|
8
14
|
module API
|
15
|
+
class Server < Roda
|
9
16
|
|
10
|
-
|
11
|
-
plugin
|
12
|
-
end
|
17
|
+
plugin :multi_route
|
18
|
+
plugin :render, { engine: 'yajl', views: File.expand_path("views", File.dirname(__FILE__)) }
|
13
19
|
|
14
|
-
|
15
|
-
|
20
|
+
require_relative 'routes/channels'
|
21
|
+
require_relative 'routes/events'
|
16
22
|
|
17
|
-
|
23
|
+
route do |r|
|
24
|
+
r.on 'apps/:app_id' do |app_id|
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
authenticate(app_id)
|
27
|
+
|
28
|
+
r.get do
|
29
|
+
r.route 'channels'
|
30
|
+
end
|
22
31
|
|
23
|
-
|
24
|
-
|
32
|
+
r.post do
|
33
|
+
r.route 'events'
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Garufa
|
2
|
+
module API
|
3
|
+
class Stats
|
4
|
+
|
5
|
+
attr_reader :subscriptions
|
6
|
+
|
7
|
+
def initialize(subscriptions)
|
8
|
+
@subscriptions = subscriptions
|
9
|
+
end
|
10
|
+
|
11
|
+
def single_channel(channel)
|
12
|
+
{ size: channel_size(channel), presence: presence(channel) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def all_channels
|
16
|
+
subscriptions.each_with_object({}) do |(channel, _), stats|
|
17
|
+
stats[channel] = single_channel(channel)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def channel_size(channel)
|
24
|
+
(subscriptions[channel] || []).size
|
25
|
+
end
|
26
|
+
|
27
|
+
def presence(channel)
|
28
|
+
return unless channel.start_with?('presence-')
|
29
|
+
|
30
|
+
data = { ids: [], hash: {} }
|
31
|
+
|
32
|
+
(subscriptions[channel] || []).each do |sub|
|
33
|
+
|
34
|
+
channel_data = JSON.parse(sub.channel_data)
|
35
|
+
id, info = channel_data.values_at('user_id', 'user_info')
|
36
|
+
|
37
|
+
next if data[:ids].include?(id)
|
38
|
+
|
39
|
+
data[:ids] << id
|
40
|
+
data[:hash][id] = info
|
41
|
+
end
|
42
|
+
|
43
|
+
data.merge(count: data[:ids].count)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/garufa/subscriptions.rb
CHANGED
@@ -5,19 +5,21 @@ module Garufa
|
|
5
5
|
module Subscriptions
|
6
6
|
extend self
|
7
7
|
|
8
|
+
@semaphore = Mutex.new
|
9
|
+
|
8
10
|
def all
|
9
11
|
subscriptions
|
10
12
|
end
|
11
13
|
|
12
14
|
def add(subscription)
|
13
15
|
subs = subscriptions[subscription.channel] ||= Set.new
|
14
|
-
subs.add subscription
|
16
|
+
@semaphore.synchronize { subs.add subscription }
|
15
17
|
end
|
16
18
|
|
17
19
|
def remove(subscription)
|
18
20
|
channel = subscription.channel
|
19
21
|
subscriptions[channel].delete subscription
|
20
|
-
subscriptions.delete(channel) if channel_size(channel)
|
22
|
+
subscriptions.delete(channel) if channel_size(channel).zero?
|
21
23
|
end
|
22
24
|
|
23
25
|
def notify(channels, event, options = {})
|
@@ -27,17 +29,21 @@ module Garufa
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def notify_channel(channel, event, options)
|
30
|
-
return if channel_size(channel)
|
32
|
+
return if channel_size(channel).zero?
|
31
33
|
|
32
|
-
subscriptions[channel]
|
33
|
-
# Skip notifying if the same socket_id is provided
|
34
|
-
next if sub.socket_id == options[:socket_id]
|
34
|
+
subs = subscriptions[channel]
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
@semaphore.synchronize {
|
37
|
+
subs.each do |sub|
|
38
|
+
# Skip notifying if the same socket_id is provided
|
39
|
+
next if sub.socket_id == options[:socket_id]
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
+
# Skip notifying the same member (probably from different tabs)
|
42
|
+
next if sub.presence_channel? and sub.channel_data == options[:data]
|
43
|
+
|
44
|
+
sub.notify Message.channel_event(channel, event, options[:data])
|
45
|
+
end
|
46
|
+
}
|
41
47
|
end
|
42
48
|
|
43
49
|
def include?(subscription)
|
@@ -46,34 +52,7 @@ module Garufa
|
|
46
52
|
end
|
47
53
|
|
48
54
|
def channel_size(channel)
|
49
|
-
|
50
|
-
subs ? subs.size : 0
|
51
|
-
end
|
52
|
-
|
53
|
-
def presence_stats(channel)
|
54
|
-
return unless channel.start_with?('presence-')
|
55
|
-
|
56
|
-
data = { ids: [], hash: {} }
|
57
|
-
|
58
|
-
(subscriptions[channel] || []).each do |sub|
|
59
|
-
|
60
|
-
channel_data = JSON.parse(sub.channel_data)
|
61
|
-
id, info = channel_data.values_at('user_id', 'user_info')
|
62
|
-
|
63
|
-
next if data[:ids].include? id
|
64
|
-
|
65
|
-
data[:ids] << id
|
66
|
-
data[:hash][id] = info
|
67
|
-
end
|
68
|
-
|
69
|
-
data.merge(count: data[:ids].count)
|
70
|
-
end
|
71
|
-
|
72
|
-
def channel_stats(channel)
|
73
|
-
{
|
74
|
-
size: channel_size(channel),
|
75
|
-
presence: presence_stats(channel)
|
76
|
-
}
|
55
|
+
(subscriptions[channel] || []).size
|
77
56
|
end
|
78
57
|
|
79
58
|
private
|
data/lib/garufa/version.rb
CHANGED
data/test/api.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
module Garufa
|
4
|
+
|
5
|
+
describe API do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
include Garufa::Test::RackHelpers
|
8
|
+
|
9
|
+
def app
|
10
|
+
API::Server
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:app_id) { Garufa::Config[:app_id] }
|
14
|
+
let(:uri) { URI.parse("/apps/#{app_id}") }
|
15
|
+
|
16
|
+
describe 'Authentication' do
|
17
|
+
describe 'When app_id is invalid' do
|
18
|
+
|
19
|
+
let(:app_id) { "invalid-app-id" }
|
20
|
+
|
21
|
+
it 'should return 400 status code' do
|
22
|
+
signed_post uri
|
23
|
+
last_response.status.must_equal 400
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should response with error message' do
|
27
|
+
signed_post uri
|
28
|
+
message = "Token validated, but invalid for app #{app_id}"
|
29
|
+
last_response.body.must_equal message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'When request is not signed' do
|
34
|
+
it 'should return 401 status code' do
|
35
|
+
post uri.path
|
36
|
+
last_response.status.must_equal 401
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'When request is signed' do
|
41
|
+
it 'should not return 401 status code' do
|
42
|
+
signed_post uri
|
43
|
+
last_response.status.wont_equal 401
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'events triggering' do
|
49
|
+
|
50
|
+
let(:handler) { Minitest::Mock.new }
|
51
|
+
|
52
|
+
describe 'requests to /events' do
|
53
|
+
|
54
|
+
let(:uri) { URI.parse("/apps/#{app_id}/events") }
|
55
|
+
|
56
|
+
before do
|
57
|
+
handler.expect :handle, nil, [String]
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should handle events' do
|
61
|
+
API::EventHandler.stub :new, handler do
|
62
|
+
signed_post uri
|
63
|
+
handler.verify
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should response 202 status code' do
|
68
|
+
API::EventHandler.stub :new, handler do
|
69
|
+
signed_post uri
|
70
|
+
last_response.status.must_equal 202
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should response empty json object' do
|
75
|
+
API::EventHandler.stub :new, handler do
|
76
|
+
signed_post uri
|
77
|
+
last_response.body.must_equal '{}'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '/channels/:channel/events' do
|
83
|
+
|
84
|
+
let(:channel) { 'channel-1' }
|
85
|
+
let(:uri) { URI.parse("/apps/#{app_id}/channels/#{channel}/events") }
|
86
|
+
|
87
|
+
before do
|
88
|
+
handler.expect :handle_legacy, nil, [String, channel, Hash]
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should handle legacy events' do
|
92
|
+
API::EventHandler.stub :new, handler do
|
93
|
+
signed_post uri
|
94
|
+
handler.verify
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should response 202 status code' do
|
99
|
+
API::EventHandler.stub :new, handler do
|
100
|
+
signed_post uri
|
101
|
+
last_response.status.must_equal 202
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should response empty json object' do
|
106
|
+
API::EventHandler.stub :new, handler do
|
107
|
+
signed_post uri
|
108
|
+
last_response.body.must_equal '{}'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe 'When getting channels info' do
|
115
|
+
|
116
|
+
let(:uri) { URI.parse("/apps/#{app_id}/channels") }
|
117
|
+
|
118
|
+
describe 'requests to /channels' do
|
119
|
+
it 'should response 200 status code' do
|
120
|
+
signed_get uri
|
121
|
+
last_response.status.must_equal 200
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should response with valid JSON' do
|
125
|
+
signed_get uri
|
126
|
+
JSON.parse(last_response.body).must_be_kind_of Hash
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'requests to /channels/presence-channel-1' do
|
131
|
+
it 'should response 200 status code' do
|
132
|
+
uri.path += '/presence-channel-1'
|
133
|
+
signed_get uri
|
134
|
+
last_response.status.must_equal 200
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should response with valid JSON' do
|
138
|
+
signed_get uri
|
139
|
+
uri.path += '/presence-channel-1'
|
140
|
+
signed_get uri
|
141
|
+
JSON.parse(last_response.body).must_be_kind_of Hash
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
describe 'requests to /channels/presence-channel-1/users' do
|
147
|
+
it 'should response 200 status code' do
|
148
|
+
uri.path += '/presence-channel-1/users'
|
149
|
+
signed_get uri
|
150
|
+
last_response.status.must_equal 200
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'requests to /channels/non-presence-channel-1' do
|
155
|
+
it 'should response 200 status code' do
|
156
|
+
uri.path += '/non-presence-channel-1'
|
157
|
+
signed_get uri
|
158
|
+
last_response.status.must_equal 200
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'requests to /channel-1/users' do
|
163
|
+
it 'should response 200 status code' do
|
164
|
+
uri.path += '/channel-1/users'
|
165
|
+
signed_get uri
|
166
|
+
last_response.status.must_equal 400
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
data/test/connection.rb
CHANGED
@@ -2,7 +2,9 @@ require_relative 'helper'
|
|
2
2
|
require 'logger'
|
3
3
|
|
4
4
|
module Garufa
|
5
|
+
|
5
6
|
describe Connection do
|
7
|
+
include Garufa::Test::ConnectionHelpers
|
6
8
|
|
7
9
|
before do
|
8
10
|
@socket = MiniTest::Mock.new
|
@@ -48,7 +50,7 @@ module Garufa
|
|
48
50
|
|
49
51
|
let(:channel) { 'private-ch1' }
|
50
52
|
let(:app_key) { Config[:app_key] }
|
51
|
-
let(:signature) {
|
53
|
+
let(:signature) { sign_string(@connection.socket_id, channel) }
|
52
54
|
let(:data) { { event: 'pusher:subscribe', data: { channel: channel, auth: "#{app_key}:#{signature}" } } }
|
53
55
|
|
54
56
|
it 'should response with subscription_succeeded' do
|
data/test/helper.rb
CHANGED
@@ -1,14 +1,50 @@
|
|
1
1
|
require 'minitest'
|
2
2
|
require 'minitest/autorun'
|
3
3
|
require 'minitest/mock'
|
4
|
+
require 'rack/test'
|
5
|
+
require 'digest/md5'
|
4
6
|
|
5
7
|
require_relative "../lib/garufa"
|
6
8
|
|
9
|
+
Garufa::Config[:app_id] = '123123123'
|
7
10
|
Garufa::Config[:app_key] = '123123-123123'
|
8
|
-
Garufa::Config[:secret]
|
11
|
+
Garufa::Config[:secret] = '456456-456456'
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
module Garufa
|
14
|
+
module Test
|
15
|
+
|
16
|
+
module ConnectionHelpers
|
17
|
+
def sign_string(socket_id, custom_string = nil)
|
18
|
+
string = [socket_id, custom_string].join(':')
|
19
|
+
secret = Garufa::Config[:secret]
|
20
|
+
digest = OpenSSL::Digest::SHA256.new
|
21
|
+
|
22
|
+
OpenSSL::HMAC.hexdigest(digest, secret, string)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module RackHelpers
|
27
|
+
def sign_params(verb, uri, params = {})
|
28
|
+
token = Signature::Token.new(Garufa::Config[:app_key], Garufa::Config[:secret])
|
29
|
+
request = Signature::Request.new(verb.to_s.upcase, uri.path, params)
|
30
|
+
|
31
|
+
params.merge(request.sign(token))
|
32
|
+
end
|
33
|
+
|
34
|
+
def signed_post(uri, params = {})
|
35
|
+
if params.any?
|
36
|
+
body_md5 = Digest::MD5.hexdigest(params.to_json)
|
37
|
+
end
|
38
|
+
|
39
|
+
query_params = sign_params(:post, uri, params.merge(body_md5: body_md5))
|
40
|
+
uri.query = URI.encode_www_form(query_params)
|
41
|
+
|
42
|
+
post uri.to_s, params
|
43
|
+
end
|
44
|
+
|
45
|
+
def signed_get(uri)
|
46
|
+
get uri.to_s, sign_params(:get, uri)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
14
50
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: garufa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Manuel Cuello
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: goliath
|
@@ -53,19 +53,19 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.3.5
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: roda
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 2.4.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 2.4.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: signature
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.2.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rack-test
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.6.3
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.6.3
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: rake
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -148,22 +162,16 @@ files:
|
|
148
162
|
- README.md
|
149
163
|
- Rakefile
|
150
164
|
- bin/garufa
|
151
|
-
- bin/garufa.pid
|
152
165
|
- garufa.gemspec
|
153
166
|
- lib/garufa.rb
|
154
167
|
- lib/garufa/api/authentication.rb
|
155
168
|
- lib/garufa/api/body_reader.rb
|
156
|
-
- lib/garufa/api/channel_filter.rb
|
157
|
-
- lib/garufa/api/channel_stats.rb
|
158
|
-
- lib/garufa/api/channels.rb
|
159
169
|
- lib/garufa/api/event_handler.rb
|
160
|
-
- lib/garufa/api/
|
161
|
-
- lib/garufa/api/response_writer.rb
|
170
|
+
- lib/garufa/api/filter.rb
|
162
171
|
- lib/garufa/api/routes/channels.rb
|
163
172
|
- lib/garufa/api/routes/events.rb
|
164
173
|
- lib/garufa/api/server.rb
|
165
|
-
- lib/garufa/api/
|
166
|
-
- lib/garufa/api/terminal_matcher.rb
|
174
|
+
- lib/garufa/api/stats.rb
|
167
175
|
- lib/garufa/api/views/channels.yajl
|
168
176
|
- lib/garufa/api/views/non_presence.yajl
|
169
177
|
- lib/garufa/api/views/presence.yajl
|
@@ -177,6 +185,7 @@ files:
|
|
177
185
|
- lib/garufa/subscriptions.rb
|
178
186
|
- lib/garufa/version.rb
|
179
187
|
- lib/garufa/websocket.rb
|
188
|
+
- test/api.rb
|
180
189
|
- test/connection.rb
|
181
190
|
- test/helper.rb
|
182
191
|
- test/message.rb
|
data/bin/garufa.pid
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
21238
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'garufa/subscriptions'
|
2
|
-
|
3
|
-
module Garufa
|
4
|
-
module API
|
5
|
-
module ChannelStats
|
6
|
-
def channel_stats(channel)
|
7
|
-
Subscriptions.channel_stats(channel)
|
8
|
-
end
|
9
|
-
|
10
|
-
def channels_stats
|
11
|
-
Subscriptions.all.each_with_object({}) do |(channel, _), stats|
|
12
|
-
stats[channel] = channel_stats(channel)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
data/lib/garufa/api/channels.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'cuba/render'
|
2
|
-
|
3
|
-
require 'yajl'
|
4
|
-
require 'yajl/json_gem'
|
5
|
-
require 'tilt/yajl'
|
6
|
-
|
7
|
-
require 'garufa/api/channel_filter'
|
8
|
-
require 'garufa/api/channel_stats'
|
9
|
-
require 'garufa/api/response_writer'
|
10
|
-
require 'garufa/api/terminal_matcher'
|
11
|
-
require 'garufa/api/settings_setter'
|
12
|
-
require 'garufa/api/routes/channels'
|
13
|
-
|
14
|
-
module Garufa
|
15
|
-
module API
|
16
|
-
|
17
|
-
class Channels < Cuba
|
18
|
-
plugin Cuba::Render
|
19
|
-
plugin ChannelFilter
|
20
|
-
plugin ChannelStats
|
21
|
-
plugin ResponseWriter
|
22
|
-
plugin TerminalMatcher
|
23
|
-
plugin SettingsSetter
|
24
|
-
|
25
|
-
set :render, template_engine: 'yajl'
|
26
|
-
set :render, views: File.expand_path("views", File.dirname(__FILE__))
|
27
|
-
|
28
|
-
include Routes::Channels
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/garufa/api/events.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'garufa/api/event_handler'
|
2
|
-
require 'garufa/api/body_reader'
|
3
|
-
require 'garufa/api/routes/events'
|
4
|
-
|
5
|
-
module Garufa
|
6
|
-
module API
|
7
|
-
|
8
|
-
class Events < Cuba
|
9
|
-
plugin EventHandler
|
10
|
-
plugin BodyReader
|
11
|
-
|
12
|
-
include Routes::Events
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|