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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b23c255cbedbe0579fd629e627f9ecc1b2cbfcea
4
- data.tar.gz: 21b2d4e38370195fa0274e00c8cc4eb84d51b7e3
3
+ metadata.gz: 22a0ca00cbf5a46859528cb7d432de18fd51415e
4
+ data.tar.gz: 4b78467ab0979477e6c72dd113da8e1ff06dd1ca
5
5
  SHA512:
6
- metadata.gz: 8d9c1c3cb181a9be6049d9e527da0b0c92253168da3a4d6d799d6b2ef9b43410497a282508548567359abc7325c041c83b695dbcedb3b52390500bb0d8d053d3
7
- data.tar.gz: 31e02f6f0be8d7b79d4c0d7cca0512eef4a1295a0f3965eb12ea2f4754068d2bafcf7b2dbb1c12657a515d6c321da39c444eba03a58577e6ef029064953637ad
6
+ metadata.gz: a994bc4b5497f5d286765b591119ff93739f57f8aebb186c6f0655ced8fa561538d043d8a97088bf6100f6bbf6520a44d05ec07a1cc0f5f0df74530ca0208281
7
+ data.tar.gz: b5a43947171fe24cf4e84a1c7176dc55f4f674ce6e7730f8f98a8363643dcf9199474cdaa9b2bf039ac0545e12682d38e40761ae6047547895d247e817a36d16
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  [![Build Status](https://travis-ci.org/Juanmcuello/garufa.png?branch=master)](https://travis-ci.org/Juanmcuello/garufa)
2
2
  [![Code Climate](https://codeclimate.com/github/Juanmcuello/garufa/badges/gpa.svg)](https://codeclimate.com/github/Juanmcuello/garufa)
3
3
 
4
+ ![logo](./doc/images/logo.png)
5
+
4
6
  Garufa
5
7
  ====
6
8
 
@@ -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 "cuba", "3.3.0"
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 Garufa
5
- module API
6
- module Authentication
7
- def authenticate(app_id)
8
- request = Signature::Request.new(req.request_method, req.path, req.params)
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
- if app_id != Garufa::Config[:app_id]
12
- halt([400, {}, ["Token validated, but invalid for app #{app_id}"]])
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 Garufa
2
- module API
3
- module BodyReader
4
- def read_body
5
- body = req.body.read; req.body.rewind
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
- module EventHandler
9
- def handle_events(body, channel = nil, params = {})
8
+ class EventHandler
10
9
 
11
- params.merge!(channels: [channel]) if channel
10
+ def handle(body)
11
+ notify JSON.parse(body)
12
+ end
12
13
 
13
- body_params = JSON.parse(body)
14
+ def handle_legacy(body, channel, params)
15
+ notify params.merge(channels: [channel], data: JSON.parse(body))
16
+ end
14
17
 
15
- # Some old api clients send channel and event in the url, while only data is
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
- # Process event deferred in order to response immediately.
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
@@ -0,0 +1,12 @@
1
+ module Filter
2
+ module InstanceMethods
3
+ def filter
4
+ {
5
+ info: request.params['info'].to_s.split(/\s*,\s*/),
6
+ prefix: request.params['filter_by_prefix']
7
+ }
8
+ end
9
+ end
10
+ end
11
+
12
+ Roda.plugin Filter
@@ -2,31 +2,34 @@ module Garufa
2
2
  module API
3
3
  module Routes
4
4
  module Channels
5
- def self.included(mod)
6
- mod.define do
7
- # GET channels/presence-channel
8
- on terminalPrefix("presence-") do |channel|
9
- write 'presence', stats: channel_stats(channel), filter: filter(req.params)
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/users
13
- on "(presence-.*)/users" do |channel|
14
- write 'presence_users', stats: channel_stats(channel)
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/non-presence-channel/users
18
- on ":channel/users" do |channel|
19
- res.status = 400
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
- on terminalPrefix("(?!presence-)") do |channel|
24
- write 'non_presence', stats: channel_stats(channel)
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
- on root do
29
- write 'channels', stats: channels_stats, filter: filter(req.params)
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
- def self.included(mod)
6
-
7
- mod.define do
8
- # Events
9
- on "events" do
10
- handle_events(read_body)
11
- res.status = 202
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
- # Legacy events
16
- on "channels/:channel/events" do |channel|
17
- handle_events(read_body, channel, req.GET)
18
- res.status = 202
19
- res.write '{}'
20
- end
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
@@ -1,27 +1,37 @@
1
- require 'cuba'
1
+ require 'roda'
2
+ require 'yajl'
3
+ require 'yajl/json_gem'
4
+ require 'tilt/yajl'
2
5
 
3
- require 'garufa/api/authentication'
4
- require 'garufa/api/events'
5
- require 'garufa/api/channels'
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
- class Server < Cuba
11
- plugin Authentication
12
- end
17
+ plugin :multi_route
18
+ plugin :render, { engine: 'yajl', views: File.expand_path("views", File.dirname(__FILE__)) }
13
19
 
14
- Server.define do
15
- on "apps/:app_id" do |app_id|
20
+ require_relative 'routes/channels'
21
+ require_relative 'routes/events'
16
22
 
17
- authenticate(app_id)
23
+ route do |r|
24
+ r.on 'apps/:app_id' do |app_id|
18
25
 
19
- on post do
20
- run Events
21
- end
26
+ authenticate(app_id)
27
+
28
+ r.get do
29
+ r.route 'channels'
30
+ end
22
31
 
23
- on get, 'channels' do
24
- run Channels
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
@@ -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) == 0
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) == 0
32
+ return if channel_size(channel).zero?
31
33
 
32
- subscriptions[channel].each do |sub|
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
- # Skip notifying the same member (probably from different tabs)
37
- next if sub.presence_channel? and sub.channel_data == options[:data]
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
- sub.notify Message.channel_event(channel, event, options[:data])
40
- end
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
- subs = subscriptions[channel]
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
@@ -1,3 +1,3 @@
1
1
  module Garufa
2
- VERSION = '1.1.1'
2
+ VERSION = '1.1.2'
3
3
  end
@@ -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
@@ -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) { sign(@connection.socket_id, channel) }
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
@@ -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] = '456456-456456'
11
+ Garufa::Config[:secret] = '456456-456456'
9
12
 
10
- def sign(socket_id, custom_string = nil)
11
- string_to_sign = [socket_id, custom_string].join(':')
12
- digest = OpenSSL::Digest::SHA256.new
13
- return OpenSSL::HMAC.hexdigest(digest, Garufa::Config[:secret], string_to_sign)
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.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: 2015-07-13 00:00:00.000000000 Z
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: cuba
56
+ name: roda
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 3.3.0
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: 3.3.0
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/events.rb
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/settings_setter.rb
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
@@ -1 +0,0 @@
1
- 21238
@@ -1,12 +0,0 @@
1
- module Garufa
2
- module API
3
- module ChannelFilter
4
- def filter(params)
5
- {
6
- info: params['info'].to_s.split(/\s*,\s*/),
7
- prefix: params['filter_by_prefix']
8
- }
9
- end
10
- end
11
- end
12
- end
@@ -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
-
@@ -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
@@ -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
@@ -1,9 +0,0 @@
1
- module Garufa
2
- module API
3
- module ResponseWriter
4
- def write(template, locals)
5
- res.write partial(template, locals)
6
- end
7
- end
8
- end
9
- end
@@ -1,15 +0,0 @@
1
- module Garufa
2
- module API
3
- module SettingsSetter
4
- module ClassMethods
5
- def set(key, value)
6
- if value.is_a? Hash
7
- settings[key].merge! value
8
- else
9
- settings[key] = value
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,9 +0,0 @@
1
- module Garufa
2
- module API
3
- module TerminalMatcher
4
- def terminalPrefix(prefix)
5
- /(#{prefix}((?!\/).)*)\z/
6
- end
7
- end
8
- end
9
- end