garufa 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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