shove 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/Gemfile +1 -2
  2. data/README.markdown +57 -91
  3. data/Rakefile +0 -23
  4. data/lib/shove.rb +3 -70
  5. data/lib/shove/app.rb +40 -33
  6. data/lib/shove/client/channel.rb +4 -0
  7. data/lib/shove/client/connection.rb +32 -14
  8. data/lib/shove/http/request.rb +2 -2
  9. data/lib/shove/protocol.rb +3 -1
  10. data/shove.gemspec +1 -3
  11. data/spec/cassettes/should_be_able_to_authorize_with_the_server.yml +10 -6
  12. data/spec/cassettes/should_deny_a_connection.yml +10 -6
  13. data/spec/cassettes/should_deny_a_control_to_a_client.yml +10 -6
  14. data/spec/cassettes/should_deny_a_publishing_to_a_client.yml +10 -6
  15. data/spec/cassettes/should_deny_a_subscriptions_to_a_client.yml +10 -6
  16. data/spec/cassettes/should_deny_publishing_on_a_channel_context.yml +10 -6
  17. data/spec/cassettes/should_deny_subscriptions_on_a_channel_context.yml +10 -6
  18. data/spec/cassettes/should_get_a_set_of_nodes_for_the_network.yml +11 -7
  19. data/spec/cassettes/should_grant_a_connection.yml +10 -6
  20. data/spec/cassettes/should_grant_a_control_to_a_client.yml +11 -7
  21. data/spec/cassettes/should_grant_a_publishing_to_a_client.yml +10 -6
  22. data/spec/cassettes/should_grant_a_subscriptions_to_a_client.yml +10 -6
  23. data/spec/cassettes/should_grant_publishing_on_a_channel_context.yml +10 -6
  24. data/spec/cassettes/should_grant_subscriptions_on_a_channel_context.yml +10 -6
  25. data/spec/cassettes/should_publish_on_a_channel_context.yml +10 -6
  26. data/spec/cassettes/should_publish_to_a_client.yml +10 -6
  27. data/spec/helper.rb +0 -2
  28. data/spec/shove_client_spec.rb +39 -30
  29. data/spec/shove_http_spec.rb +27 -31
  30. metadata +20 -40
  31. data/bin/shove +0 -169
  32. data/lib/shove/app_directory.rb +0 -103
  33. data/spec/app_directory_spec.rb +0 -66
  34. data/spec/cassettes/should_authorize_on_a_channel.yml +0 -26
  35. data/spec/cassettes/should_authorize_oneself.yml +0 -24
  36. data/spec/cassettes/should_cancel_a_binding.yml +0 -24
  37. data/spec/cassettes/should_configure_the_default.yml +0 -24
  38. data/spec/cassettes/should_configure_the_from_the_previous_test.yml +0 -24
  39. data/spec/cassettes/should_create_a_channel_context.yml +0 -24
  40. data/spec/cassettes/should_get_a_subscribe_granted_event.yml +0 -24
  41. data/spec/cassettes/should_publish.yml +0 -24
  42. data/spec/cassettes/should_receive_an_unsubscribe_event.yml +0 -24
  43. data/spec/cassettes/should_receive_messages_on_a_channel.yml +0 -24
  44. data/spec/cassettes/should_send_a_connect_op.yml +0 -24
  45. data/spec/cassettes/should_send_a_connect_op_with_an_id.yml +0 -24
  46. data/spec/cassettes/should_spawn_a_client.yml +0 -24
  47. data/spec/cassettes/should_subscribe_to_a_channel.yml +0 -24
  48. data/spec/cassettes/should_trigger_a_connect_denied_event.yml +0 -24
  49. data/spec/cassettes/should_trigger_a_connect_event.yml +0 -24
  50. data/spec/cassettes/should_trigger_a_disconnect_event.yml +0 -24
  51. data/spec/cassettes/should_trigger_an_error_event.yml +0 -24
  52. data/spec/cassettes/should_unsubscribe_from_a_channel.yml +0 -24
  53. data/spec/cassettes/should_update_the_default_app.yml +0 -24
data/Gemfile CHANGED
@@ -16,5 +16,4 @@ end
16
16
 
17
17
  gem "em-http-request", ">= 1.0.0"
18
18
  gem "em-ws-client", ">= 0.2.0"
19
- gem "yajl-ruby", ">= 1.1.0"
20
- gem "confstruct", ">= 0.2.1"
19
+ gem "yajl-ruby", ">= 1.1.0"
@@ -1,6 +1,6 @@
1
- shove ruby client
2
- =================
3
- Ruby client and CLI for the shove.io HTTP and WebSocket APIs
1
+ shove
2
+ =====
3
+ HTTP and WebSocket clients for shove.io
4
4
 
5
5
  <a name="installation"></a>
6
6
  Installation
@@ -11,53 +11,42 @@ gem install shove
11
11
  ```
12
12
 
13
13
  <a name="configuration"></a>
14
- Configuring Shove
15
- -----------------
14
+ Using Shove
15
+ -----------
16
16
 
17
- If you are using a single shove app within your project, you can configure
18
- shove though the Shove module:
17
+ To use shove, you must first create a Shove::App object.
19
18
 
20
19
  ```ruby
21
- Shove.configure do
22
- app_id "myappid"
23
- app_key "myappkey"
24
- end
25
- ```
26
-
27
- If you want to work with different shove apps in one project, you can
28
- create App objects
29
-
30
- ```ruby
31
- app = Shove::App.new do
32
- app_id "myappid"
33
- app_key "myappkey"
34
- end
20
+ app = Shove::App.new(
21
+ app_id: "myappid",
22
+ app_key: "myappkey"
23
+ )
35
24
  ```
36
25
 
37
- Grab your App ID and App Key from shove: [https://shove.io][0]
26
+ Get your app_id, and app_key at [shove.io][0]
38
27
 
39
28
  <a name="http_client"></a>
40
29
  Using the HTTP Client
41
30
  ---------------------
42
31
  The HTTP client gives publishing and access control capabilities without
43
- a persistent WebSocket connection. The HTTP client does not act as a subscriber.
32
+ a persistent WebSocket connection. The HTTP client cannot act as a subscriber.
44
33
 
45
- Simple Publish
34
+ Publish to a channel
46
35
 
47
36
  ```ruby
48
- Shove.channel("notifications").publish("Hello World!")
37
+ app.channel("notifications").publish("Hello World!")
49
38
  ```
50
39
 
51
40
  Publish Direct
52
41
 
53
42
  ```ruby
54
- Shove.channel("direct:buddy").publish("Hey buddy")
43
+ app.channel("direct:buddy").publish("Hey buddy")
55
44
  ```
56
45
 
57
46
  Publish and handle the HTTP response
58
47
 
59
48
  ```ruby
60
- Shove.channel("notifications").publish("...") do |response|
49
+ app.channel("notifications").publish("...") do |response|
61
50
  if reponse.error?
62
51
  puts "#{response.status} - #{response.error}"
63
52
  end
@@ -70,25 +59,25 @@ granular security.
70
59
  Grant subscription on the notifications channel
71
60
 
72
61
  ```ruby
73
- Shove.channel("notifications").grant_subscribe("dan@shove.io")
62
+ app.channel("notifications").grant_subscribe("dan@shove.io")
74
63
  ```
75
64
 
76
65
  Grant subscription on all channels to client dan
77
66
 
78
67
  ```ruby
79
- Shove.channel("*").grant_subscribe("dan@shove.io")
68
+ app.channel("*").grant_subscribe("dan@shove.io")
80
69
  ```
81
70
 
82
71
  Grant publishing on chat:client_22733 channel to client dan
83
72
 
84
73
  ```ruby
85
- Shove.channel("chat:client_22733").grant_publish("dan")
74
+ app.channel("chat:client_22733").grant_publish("dan")
86
75
  ```
87
76
 
88
77
  Deny publishing on chat:client_22733 channel to dan
89
78
 
90
79
  ```ruby
91
- Shove.channel("chat:client_22733").deny_publish("dan")
80
+ app.channel("chat:client_22733").deny_publish("dan")
92
81
  ```
93
82
 
94
83
  Sometimes it's easier to give out an access key to a specific
@@ -98,37 +87,37 @@ channel, which is also an option.
98
87
  Channel Keys
99
88
  ------------
100
89
  You can generate channel keys which allow clients of
101
- your shove network to publish and subscribe to specific
90
+ your shove network to subscribe or publish to specific
102
91
  channels.
103
92
 
104
93
  Example: Create a key for the channel groups:788
105
94
 
106
95
  ```ruby
107
- key = Shove.channel_key "group:788"
96
+ key = app.channel_key "group:788"
108
97
  ```
109
98
 
110
- If it's for a particular App, use:
99
+ Subscribe only
111
100
 
112
101
  ```ruby
113
- key = app.channel_key "group:788"
102
+ key = app.subscribe_key "group:788"
114
103
  ```
115
104
 
116
105
  This functionality becomes useful when you want to give
117
- you site users access. A little haml for you:
106
+ you site users access. In your view:
118
107
 
119
- ```haml
120
- :javascript
121
- var channel = "#{@channel}";
122
- var key = "#{@shove.channel_key(@channel)}";
108
+ ```erb
109
+ var channel = "<%= @channel %>";
110
+ var key = "<%= @app.channel_key(@channel) %>";
123
111
  ```
124
112
 
125
- Note: Channel keys are based off the app key. So, in order for
126
- them to work, you must specify the app key:
113
+ Note: Channel keys are based off the app key (master key). So, in order for
114
+ them to work, you must specify the app key in your app.
127
115
 
128
116
  ```ruby
129
- Shove.configure do
130
- app_key "key"
131
- end
117
+ app = Shove::App.new(
118
+ app_id: "myappid",
119
+ app_key: "myappkey"
120
+ )
132
121
  ```
133
122
 
134
123
  <a name="websocket_client"></a>
@@ -139,28 +128,15 @@ requires that you are running an EventMachine reactor.
139
128
 
140
129
  ```ruby
141
130
  EM.run do
142
- app = Shove::App.new do
143
- app_id "myapp"
144
- end
145
-
146
- app.connect
131
+ app = Shove::App.new(
132
+ app_id "myapp",
133
+ app_key: "myappkey"
134
+ )
147
135
 
148
- # alternatively, supply your user id
149
- client = app.connect "unique_id"
136
+ client = app.connect
150
137
  end
151
138
  ```
152
139
 
153
- ### Authorization
154
- The client is treated like any other websocket
155
- client and must be authorized to publish and subscribe.
156
-
157
- ```ruby
158
- client.authorize "app_key"
159
-
160
- # self authorize a particular channel
161
- client.channel("channel").authorize "channel_key"
162
- ```
163
-
164
140
  ### Client events
165
141
 
166
142
  Connect event:
@@ -195,7 +171,7 @@ client.on("connect_denied") do |id|
195
171
  end
196
172
  ```
197
173
 
198
- ### Publish and Subscribe
174
+ ### Channels & Publish and Subscribe
199
175
 
200
176
  Subscribe to a channel or get a subscribed channel
201
177
 
@@ -265,37 +241,27 @@ channel.publish("hi!")
265
241
  channel.publish(obj.to_json)
266
242
  ```
267
243
 
268
- Using the Command Line
269
- ----------------------
270
-
271
- A CLI utility is included with the gem, run help to see options
272
-
273
- ```bash
274
- shove help
275
- ```
276
-
277
- Publish a message
278
-
279
- ```bash
280
- shove publish -c channel1 -m "Hello world!"
281
- ```
282
-
283
- Publish to a specific app
284
-
285
- ```bash
286
- shove publish -a app_id -c chan1 -m "hi"
287
- ```
244
+ <a name="websocket_client"></a>
245
+ WebSocket Client without App Key
246
+ --------------------------------
247
+ If you are connecting to someone elses app
248
+ and have limited scope and access, you can get by.
288
249
 
289
- Set the default app for the CLI
250
+ ```ruby
251
+ EM.run do
252
+ app = Shove::App.new(
253
+ app_id "myapp"
254
+ )
290
255
 
291
- ```bash
292
- shove apps:default -a app_id
293
- ```
256
+ client = app.connect "connect-key"
294
257
 
295
- Watch all activity on a channel
258
+ channel = client.channel("channel")
259
+ channel.auth "channelkey"
296
260
 
297
- ```bash
298
- shove watch -c chan
261
+ channel.on("message") do |message|
262
+ puts message
263
+ end
264
+ end
299
265
  ```
300
266
 
301
267
  [0]: https://shove.io
data/Rakefile CHANGED
@@ -28,26 +28,3 @@ task :autospec => :spec do
28
28
  end
29
29
 
30
30
  end
31
-
32
- desc "Generate the README HTML"
33
- task :readme do
34
-
35
- require "redcarpet"
36
- require "albino"
37
-
38
- # Create a custom renderer that uses albino to
39
- # make pretty code
40
- class Colorizer < Redcarpet::Render::HTML
41
- def block_code(code, language)
42
- Albino.colorize(code, language)
43
- end
44
- end
45
-
46
- content = Redcarpet::Markdown.new(Colorizer, :fenced_code_blocks => true)
47
- .render(File.read("README.markdown"))
48
-
49
- File.open("README.html", "w") do |f|
50
- f << content
51
- end
52
-
53
- end
@@ -7,7 +7,6 @@ require "em-http-request"
7
7
  require "em-ws-client"
8
8
  require "yajl"
9
9
  require "yaml"
10
- require "confstruct"
11
10
  require "digest/sha1"
12
11
 
13
12
  ##
@@ -18,80 +17,14 @@ require "digest/sha1"
18
17
  # See https://github.com/shove/shove for js client documentation
19
18
  module Shove
20
19
 
21
- Version = "1.0.7"
22
-
23
- class ShoveException < Exception; end
24
-
25
- class << self
26
-
27
- attr_accessor :config, :app
28
-
29
- # configure shover
30
- # +settings+ the settings for the created client as
31
- # a string for a yaml file, or as a hash
32
- def configure params=nil, &block
33
-
34
- unless defined? @config
35
- @config = Confstruct::Configuration.new do
36
- api_url "https://api.shove.io"
37
- end
38
- end
39
-
40
- if params
41
- @config.configure params
42
- end
20
+ Version = "1.0.8"
43
21
 
44
- if block
45
- @config.configure(&block)
46
- end
47
-
48
- unless defined? @app
49
- @app = App.new(@config)
50
- else
51
-
52
- end
53
- end
54
-
55
- # fetch a channel by name
56
- # +name+ the name of the channel
57
- def channel name
58
- @app.channel(name)
59
- end
60
-
61
- # fetch a client by id
62
- def client id
63
- @app.client(id)
64
- end
65
-
66
- # validate network settings
67
- # used for the CLI
68
- def valid?
69
- @app.valid?
70
- end
71
-
72
- # fetch the available stream nodes
73
- # for this network.
74
- def hosts
75
- @app.hosts
76
- end
77
-
78
- # Connect to the default app with a
79
- # WebSocket connection
80
- def connect
81
- @app.connect
82
- end
83
-
84
- # Create a channel key
85
- # +channel+ the name of the channel
86
- def channel_key channel
87
- @app.channel_key channel
88
- end
22
+ # Exception class for all shove exception
23
+ class ShoveException < Exception; end
89
24
 
90
- end
91
25
  end
92
26
 
93
27
  require "shove/app"
94
- require "shove/app_directory"
95
28
  require "shove/protocol"
96
29
  require "shove/client/connection"
97
30
  require "shove/client/channel"
@@ -1,38 +1,24 @@
1
1
  module Shove
2
2
  class App
3
3
 
4
- attr_accessor :config
4
+ attr_accessor :app_key, :app_id, :api_url, :ws_url
5
5
 
6
6
  # create an API client
7
7
  # +config+ optional Confstruct
8
8
  # +&block+ config block
9
9
  # Example:
10
- # Shove::App.new do
11
- # app_id "myappid"
12
- # app_key "myappkey"
13
- # end
14
- def initialize config=Confstruct::Configuration.new, &block
15
- @config = config
16
- configure(&block)
17
- end
18
-
19
- def configure params={}, &block
20
-
21
- @config.configure do
22
- api_url Shove.config.api_url || "https://api.shove.io"
23
- end
10
+ # Shove::App.new(
11
+ # app_id: "myappid"
12
+ # app_key: "myappkey"
13
+ # )
14
+ def initialize config={}
15
+ @config = config
16
+ @app_id = config[:app_id]
17
+ @app_key = config[:app_key]
18
+ @api_url = config[:api_url] || "https://api.shove.io"
19
+ @ws_url = config[:ws_url]
24
20
 
25
- if params
26
- @config.configure params
27
- end
28
-
29
- if block
30
- @config.configure(&block)
31
- end
32
-
33
- unless @config.app_id
34
- raise ShoveException.new("App ID required")
35
- end
21
+ raise ShoveException.new("App ID required") unless @app_id
36
22
  end
37
23
 
38
24
  # is the app valid?
@@ -43,7 +29,7 @@ module Shove
43
29
 
44
30
  # get a list of websocket hosts
45
31
  def hosts
46
- request("hosts").exec_sync(:get).parse
32
+ @hosts ||= request("hosts").exec_sync(:get).parse
47
33
  end
48
34
 
49
35
  # create a channel context for acting on a channel
@@ -60,29 +46,50 @@ module Shove
60
46
 
61
47
  # the base URL based on the settings
62
48
  def url
63
- "#{@config.api_url}/apps/#{@config.app_id}"
49
+ "#{@api_url}/apps/#{@app_id}"
64
50
  end
65
51
 
66
52
  # Create a default request object with the base URL
67
53
  # +path+ extra path info
68
54
  def request path
69
- Http::Request.new("#{url}/#{path}", @config)
55
+ Http::Request.new("#{url}/#{path}", self)
70
56
  end
71
57
 
72
58
  # Generate a channel key for a client to self authorize
73
59
  # publish and subscribe actions.
74
60
  # +channel+ the name of the channel
75
61
  def channel_key channel
76
- Digest::SHA1.hexdigest "#{@config.app_key}-#{channel}"
62
+ Digest::SHA1.hexdigest "#{@app_key}-#{channel}!"
63
+ end
64
+
65
+ # Generate a channel key for a client to self authorize
66
+ # publish and subscribe actions.
67
+ # +channel+ the name of the channel
68
+ def publish_key channel
69
+ channel_key channel
70
+ end
71
+
72
+ # Generate a channel key for a client to self authorize
73
+ # subscribe actions.
74
+ # +channel+ the name of the channel
75
+ def subscribe_key channel
76
+ Digest::SHA1.hexdigest "#{@app_key}-#{channel}"
77
+ end
78
+
79
+ # Generate a connect key for a client to self authorize
80
+ # publish and subscribe actions.
81
+ # +channel+ the name of the channel
82
+ def connect_key
83
+ Digest::SHA1.hexdigest "#{@app_key}-connect"
77
84
  end
78
85
 
79
86
  ####
80
87
 
81
88
  # Connect to shove as a client in the current process
82
89
  # +id+ optional shove id to supply
83
- def connect id=nil
84
- client = Client::Connection.new(self, id)
85
- client.connect
90
+ def connect connect_key=nil
91
+ client = Client::Connection.new(self)
92
+ client.connect connect_key
86
93
  client
87
94
  end
88
95