socky-server 0.4.1 → 0.5.0.beta1

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.
Files changed (65) hide show
  1. data/.gitignore +0 -4
  2. data/.travis.yml +6 -0
  3. data/CHANGELOG.md +11 -5
  4. data/Gemfile +2 -0
  5. data/README.md +47 -68
  6. data/Rakefile +5 -7
  7. data/config.ru +19 -0
  8. data/example/config.yml +4 -0
  9. data/lib/socky/server.rb +23 -0
  10. data/lib/socky/server/application.rb +51 -0
  11. data/lib/socky/server/channel.rb +30 -0
  12. data/lib/socky/server/channel/base.rb +80 -0
  13. data/lib/socky/server/channel/presence.rb +49 -0
  14. data/lib/socky/server/channel/private.rb +44 -0
  15. data/lib/socky/server/channel/public.rb +43 -0
  16. data/lib/socky/server/channel/stub.rb +17 -0
  17. data/lib/socky/server/config.rb +52 -0
  18. data/lib/socky/server/connection.rb +66 -0
  19. data/lib/socky/server/http.rb +95 -0
  20. data/lib/socky/server/logger.rb +24 -0
  21. data/lib/socky/server/message.rb +35 -0
  22. data/lib/socky/server/misc.rb +18 -0
  23. data/lib/socky/server/version.rb +5 -0
  24. data/lib/socky/server/websocket.rb +43 -0
  25. data/socky-server.gemspec +5 -7
  26. data/spec/fixtures/example_config.yml +3 -0
  27. data/spec/integration/ws_channels_spec.rb +144 -0
  28. data/spec/integration/ws_connection_spec.rb +48 -0
  29. data/spec/integration/ws_presence_spec.rb +118 -0
  30. data/spec/integration/ws_rights_spec.rb +133 -0
  31. data/spec/spec_helper.rb +24 -2
  32. data/spec/support/websocket_application.rb +14 -0
  33. data/spec/unit/socky/server/application_spec.rb +54 -0
  34. data/spec/unit/socky/server/config_spec.rb +50 -0
  35. data/spec/unit/socky/server/connection_spec.rb +67 -0
  36. data/spec/unit/socky/server/message_spec.rb +64 -0
  37. metadata +93 -126
  38. data/bin/socky +0 -5
  39. data/lib/em-websocket_hacks.rb +0 -15
  40. data/lib/socky.rb +0 -75
  41. data/lib/socky/connection.rb +0 -137
  42. data/lib/socky/connection/authentication.rb +0 -99
  43. data/lib/socky/connection/finders.rb +0 -67
  44. data/lib/socky/message.rb +0 -85
  45. data/lib/socky/misc.rb +0 -74
  46. data/lib/socky/net_request.rb +0 -27
  47. data/lib/socky/options.rb +0 -39
  48. data/lib/socky/options/config.rb +0 -79
  49. data/lib/socky/options/parser.rb +0 -93
  50. data/lib/socky/runner.rb +0 -95
  51. data/spec/em-websocket_spec.rb +0 -36
  52. data/spec/files/default.yml +0 -18
  53. data/spec/files/invalid.yml +0 -1
  54. data/spec/socky/connection/authentication_spec.rb +0 -183
  55. data/spec/socky/connection/finders_spec.rb +0 -188
  56. data/spec/socky/connection_spec.rb +0 -151
  57. data/spec/socky/message_spec.rb +0 -102
  58. data/spec/socky/misc_spec.rb +0 -74
  59. data/spec/socky/net_request_spec.rb +0 -42
  60. data/spec/socky/options/config_spec.rb +0 -72
  61. data/spec/socky/options/parser_spec.rb +0 -76
  62. data/spec/socky/options_spec.rb +0 -60
  63. data/spec/socky/runner_spec.rb +0 -88
  64. data/spec/socky_spec.rb +0 -89
  65. data/spec/support/stallion.rb +0 -96
@@ -1,10 +1,10 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "socky"
3
+ require "socky/server/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "socky-server"
7
- s.version = Socky::VERSION
7
+ s.version = Socky::Server::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Bernard Potocki"]
10
10
  s.email = ["bernard.potocki@imanel.org"]
@@ -12,12 +12,10 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{Socky is a WebSocket server and client for Ruby}
13
13
  s.description = %q{Socky is a WebSocket server and client for Ruby}
14
14
 
15
- s.add_runtime_dependency 'em-websocket', '~> 0.3.0'
16
- s.add_runtime_dependency 'em-http-request'
17
- s.add_runtime_dependency 'json'
15
+ s.add_dependency 'websocket-rack', ">= 0.2.1"
16
+ s.add_dependency 'socky-authenticator', '~> 0.5.0.beta5'
17
+ s.add_dependency 'json'
18
18
  s.add_development_dependency 'rspec', '~> 2.0'
19
- s.add_development_dependency 'rack'
20
- s.add_development_dependency 'mongrel'
21
19
 
22
20
  s.files = `git ls-files`.split("\n")
23
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -0,0 +1,3 @@
1
+ debug: true
2
+ applications:
3
+ some_test_app: some_test_secret
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'WebSocket Channels' do
4
+
5
+ before { @application = Socky::Server::Application.new('test_application', 'test_secret')}
6
+ after { Socky::Server::Application.list.delete('test_application') }
7
+
8
+ context "connected to application" do
9
+ subject { mock_websocket(@application.name) }
10
+ before { subject.on_open({'PATH_INFO' => @application.name}); subject.connection.id = "1234567890" }
11
+ after { subject.on_close({}) }
12
+
13
+ context "public channel" do
14
+ let(:channel_name) { 'test_channel' }
15
+
16
+ it "should be able to join without auth" do
17
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name })
18
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
19
+ end
20
+
21
+ it "should have channel on his list after auth" do
22
+ subject.connection.channels[channel_name].should be_nil
23
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
24
+ subject.connection.channels[channel_name].should_not be_nil
25
+ end
26
+
27
+ it "should allow unsubscribing from channel" do
28
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
29
+ subject.should_receive(:send_data).with({ 'event' => 'socky:unsubscribe:success', 'channel' => channel_name })
30
+ subject.on_message({}, { 'event' => 'socky:unsubscribe', 'channel' => channel_name }.to_json)
31
+ end
32
+
33
+ it "should not have channel on his list after unsubscribing" do
34
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
35
+ subject.on_message({}, { 'event' => 'socky:unsubscribe', 'channel' => channel_name }.to_json)
36
+ subject.connection.channels[channel_name].should be_nil
37
+ end
38
+ end
39
+
40
+ context "private channel" do
41
+ let(:channel_name) { 'private-test_channel' }
42
+
43
+ it "should not be able to join without auth" do
44
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
45
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
46
+ end
47
+
48
+ it "should not be able to join with invalid auth" do
49
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
50
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'invalid' }.to_json)
51
+ end
52
+
53
+ it "should be able to join with valid auth" do
54
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name })
55
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'afdc07ceaa841db71d0d01fb2b17850b:d77b99ea70fdb487a8d6d4279cea37199b991f7fed9dd8be900c8451b344cb18' }.to_json)
56
+ end
57
+
58
+ it "should require modified auth to join with changing read rights" do
59
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
60
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => 'afdc07ceaa841db71d0d01fb2b17850b:d77b99ea70fdb487a8d6d4279cea37199b991f7fed9dd8be900c8451b344cb18' }.to_json)
61
+ end
62
+
63
+ it "should allow changing read rights with valid auth" do
64
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name })
65
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => '6e039ada5575795e53c382ba316ceb5f:18e4bb05c33e89ca446ac5d5c30dacfb7e2b81bb08ff342cd1ed5013a94549bf' }.to_json)
66
+ end
67
+
68
+ it "should require modified auth to join with changing write rights" do
69
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
70
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => 'afdc07ceaa841db71d0d01fb2b17850b:d77b99ea70fdb487a8d6d4279cea37199b991f7fed9dd8be900c8451b344cb18' }.to_json)
71
+ end
72
+
73
+ it "should allow changing read rights with valid auth" do
74
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name })
75
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => '94eebeb7b285adaf303d3644aedad77e:69943f47af7a051a75d17ea06ef00aceb8511f446d4e0dc9ef7b55cb2ea85634' }.to_json)
76
+ end
77
+
78
+ it "should ignore changing hide right" do
79
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name })
80
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'hide' => true, 'auth' => 'afdc07ceaa841db71d0d01fb2b17850b:d77b99ea70fdb487a8d6d4279cea37199b991f7fed9dd8be900c8451b344cb18' }.to_json)
81
+ end
82
+ end
83
+
84
+ context "presence channel" do
85
+ let(:channel_name) { 'presence-test_channel' }
86
+
87
+ it "should not be able to join without auth" do
88
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
89
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
90
+ end
91
+
92
+ it "should not be able to join with invalid auth" do
93
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
94
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'invalid' }.to_json)
95
+ end
96
+
97
+ it "should be able to join with valid auth" do
98
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
99
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
100
+ end
101
+
102
+ it "should require modified auth to join with changing read rights" do
103
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
104
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
105
+ end
106
+
107
+ it "should allow changing read rights with valid auth" do
108
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
109
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:cb123cdaf630653a61b7cd03941847a9a49d45d88d6c61f9858fb9754f7ad40a' }.to_json)
110
+ end
111
+
112
+ it "should require modified auth to join with changing write rights" do
113
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
114
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
115
+ end
116
+
117
+ it "should allow changing read rights with valid auth" do
118
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
119
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:d7c118d5dad01318c8be2f96bd00e2d3f13bf2893270fd60d92c89027c78e035' }.to_json)
120
+ end
121
+
122
+ it "should require modified auth to join with changing hide right" do
123
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
124
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'hide' => true, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
125
+ end
126
+
127
+ it "should allow changing hide rights with valid auth" do
128
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
129
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'hide' => true, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:2f8dfc64afdd0acc59f690f45d24b48d40fb9859dbe7dc39677b60457a64739c' }.to_json)
130
+ end
131
+
132
+ it "should require changing auth after changind user data" do
133
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:failure', 'channel' => channel_name })
134
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'data' => "{\"some\":\"data\"}", 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
135
+ end
136
+
137
+ it "should allow passing user data with valid auth" do
138
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
139
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'data' => "{\"some\":\"data\"}", 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:9cdbfc5746f67c26784f75683a0f89a70f6079f0030f48ac8193458717f0791e' }.to_json)
140
+ end
141
+ end
142
+ end
143
+
144
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'WebSocket Connection' do
4
+
5
+ before { @application = Socky::Server::Application.new('test_application', 'test_secret')}
6
+ after { Socky::Server::Application.list.delete('test_application') }
7
+
8
+ context 'Valid application' do
9
+ subject { mock_websocket(@application.name) }
10
+
11
+ it "should receive confirmation on connection" do
12
+ subject.should_receive(:send_data).with(hash_including( 'event' => 'socky:connection:established' ))
13
+ subject.on_open({'PATH_INFO' => @application.name})
14
+ end
15
+
16
+ it "should generate connection" do
17
+ subject.on_open({'PATH_INFO' => @application.name})
18
+ subject.connection.should_not be_nil
19
+ subject.connection.class.should eql(Socky::Server::Connection)
20
+ end
21
+
22
+ it "should not close connection" do
23
+ subject.should_not_receive(:on_close)
24
+ subject.on_open({'PATH_INFO' => @application.name})
25
+ end
26
+ end
27
+
28
+ context "Invalid application" do
29
+ subject { mock_websocket('invalid_name') }
30
+
31
+ it "should receive 'application invalid' error" do
32
+ subject.should_receive(:send_data).with({ 'event' => 'socky:connection:error', 'reason' => 'refused' })
33
+ subject.on_open({'PATH_INFO' => 'invalid_name'})
34
+ end
35
+
36
+ it "should generate connection" do
37
+ subject.on_open({'PATH_INFO' => 'invalid_name'})
38
+ subject.connection.should_not be_nil
39
+ subject.connection.class.should eql(Socky::Server::Connection)
40
+ end
41
+
42
+ it "should close connection" do
43
+ subject.should_receive(:on_close)
44
+ subject.on_open({'PATH_INFO' => 'invlaid_name'})
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'WebSocket Presence notification' do
4
+
5
+ before { @application = Socky::Server::Application.new('test_application', 'test_secret')}
6
+ after { Socky::Server::Application.list.delete(@application.name) }
7
+
8
+ subject { mock_websocket(@application.name) }
9
+ before { subject.on_open({'PATH_INFO' => @application.name}); subject.connection.id = "1234567890" }
10
+ after { subject.on_close({}) }
11
+ let(:channel_name) { 'presence-test_channel' }
12
+
13
+ context 'no other users on the same channel' do
14
+ it "should return empty list if no other users are on channel" do
15
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
16
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
17
+ end
18
+ it "should not receive notification about own joining to channel" do
19
+ subject.should_not_receive(:send_data).with(hash_including('event' => 'socky:member:added'))
20
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
21
+ end
22
+ it "should not receive notification about own disconnection from channel" do
23
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
24
+ subject.should_not_receive(:send_data).with(hash_including('event' => 'socky:member:removed'))
25
+ subject.on_message({}, { 'event' => 'socky:unsubscribe', 'channel' => channel_name }.to_json)
26
+ end
27
+ end
28
+
29
+ context 'other user on the same channel' do
30
+ let(:other_user) { mock_websocket(@application.name) }
31
+ before do
32
+ other_user.on_open({'PATH_INFO' => @application.name})
33
+ other_user.connection.id = "123"
34
+ other_user.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
35
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:2ed67632bf9a03e7e28068284efae222256f80dfafe798abff85455401d6000e' }.to_json)
36
+ end
37
+ after { other_user.on_close({}) }
38
+
39
+ it "should return other users list" do
40
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [{"data"=>{}, "connection_id"=>"123"}] })
41
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
42
+ end
43
+
44
+ it "should send channel join notification to other members" do
45
+ other_user.should_receive(:send_data).with({ 'event' => 'socky:member:added', 'connection_id' => subject.connection.id, 'channel' => channel_name, 'data' => {} })
46
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
47
+ end
48
+
49
+ it "should send valid user data with join notification" do
50
+ other_user.should_receive(:send_data).with({ 'event' => 'socky:member:added', 'connection_id' => subject.connection.id, 'channel' => channel_name, 'data' => { 'some' => 'data' } })
51
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'data' => "{\"some\":\"data\"}", 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:9cdbfc5746f67c26784f75683a0f89a70f6079f0030f48ac8193458717f0791e' }.to_json)
52
+ end
53
+
54
+ it "should send channel exit notification to other members" do
55
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'data' => "{\"some\":\"data\"}", 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:9cdbfc5746f67c26784f75683a0f89a70f6079f0030f48ac8193458717f0791e' }.to_json)
56
+ other_user.should_receive(:send_data).with({ 'event' => 'socky:member:removed', 'connection_id' => subject.connection.id, 'channel' => channel_name })
57
+ subject.on_message({}, { 'event' => 'socky:unsubscribe', 'channel' => channel_name }.to_json)
58
+ end
59
+ end
60
+
61
+ context 'other user on other channel' do
62
+ let(:other_user) { mock_websocket(@application.name) }
63
+ before do
64
+ other_user.on_open({'PATH_INFO' => @application.name})
65
+ other_user.connection.id = "123"
66
+ other_user.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => 'presence-other_channel', 'members' => [] })
67
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => 'presence-other_channel', 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:6861bcb873a4a9c4bcd6b7fc1bf3b170684f191ebbdb1e222614900c9243a0fa' }.to_json)
68
+ end
69
+ after { other_user.on_close({}) }
70
+
71
+ it "should return empty users list" do
72
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
73
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
74
+ end
75
+
76
+ it "should not send channel join notification to members on other channels" do
77
+ other_user.should_not_receive(:send_data).with(hash_including('event' => 'socky:member:added'))
78
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
79
+ end
80
+
81
+ it "should not send channel exit notification to members on other channels" do
82
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'data' => "{\"some\":\"data\"}", 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:9cdbfc5746f67c26784f75683a0f89a70f6079f0030f48ac8193458717f0791e' }.to_json)
83
+ other_user.should_not_receive(:send_data).with(hash_including('event' => 'socky:member:removed'))
84
+ subject.on_message({}, { 'event' => 'socky:unsubscribe', 'channel' => channel_name }.to_json)
85
+ end
86
+ end
87
+
88
+ context 'other user on the same channel but different application' do
89
+ before { @application2 = Socky::Server::Application.new('other_application', 'other_secret')}
90
+ after { Socky::Server::Application.list.delete(@application2.name) }
91
+
92
+ let(:other_user) { mock_websocket(@application2.name) }
93
+ before do
94
+ other_user.on_open({'PATH_INFO' => @application2.name})
95
+ other_user.connection.id = "123"
96
+ other_user.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
97
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:5667cf407419d95a042e4e0479f25fa4b62ed548285e80db0af0fc5262ea60c6' }.to_json)
98
+ end
99
+ after { other_user.on_close({}) }
100
+
101
+ it "should return empty users list" do
102
+ subject.should_receive(:send_data).with({ 'event' => 'socky:subscribe:success', 'channel' => channel_name, 'members' => [] })
103
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
104
+ end
105
+
106
+ it "should not send channel join notification to members on other channels" do
107
+ other_user.should_not_receive(:send_data).with(hash_including('event' => 'socky:member:added'))
108
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:72fa6a183de7aa0dbeb10db03daec3d6e9fb590c38fc1b6aee0bc69a585c16ee' }.to_json)
109
+ end
110
+
111
+ it "should not send channel exit notification to members on other channels" do
112
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'data' => "{\"some\":\"data\"}", 'auth' => 'ec7ca4b2d08958ad7f98bb5df4f63c5c:9cdbfc5746f67c26784f75683a0f89a70f6079f0030f48ac8193458717f0791e' }.to_json)
113
+ other_user.should_not_receive(:send_data).with(hash_including('event' => 'socky:member:removed'))
114
+ subject.on_message({}, { 'event' => 'socky:unsubscribe', 'channel' => channel_name }.to_json)
115
+ end
116
+ end
117
+
118
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'WebSocket Rights' do
4
+
5
+ before { @application = Socky::Server::Application.new('test_application', 'test_secret')}
6
+ after { Socky::Server::Application.list.delete('test_application') }
7
+
8
+ context "connected to application" do
9
+ subject { mock_websocket(@application.name) }
10
+ before { subject.on_open({'PATH_INFO' => @application.name}); subject.connection.id = "1234567890" }
11
+ after { subject.on_close({}) }
12
+
13
+ let(:other_user) do
14
+ return @other_user if defined?(@other_user)
15
+ other = mock_websocket(@application.name)
16
+ other.on_open({'PATH_INFO' => @application.name})
17
+ other.connection.id = "1234567891"
18
+ @other_user = other
19
+ end
20
+ after { @other_user.on_close({}) if defined?(@other_user) }
21
+
22
+ context "public channel" do
23
+ let(:channel_name) { 'test_channel' }
24
+
25
+ it "should not be able to disable read permission" do
26
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false }.to_json)
27
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name })
28
+ Socky::Server::Channel.find_or_create(@application.name, channel_name).send_data({ 'event' => 'test_event', 'channel' => channel_name })
29
+ end
30
+
31
+ it "should not be able to enable write permission" do
32
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name }.to_json)
33
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true }.to_json)
34
+ subject.should_not_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name })
35
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
36
+ end
37
+ end
38
+
39
+ context "private channel" do
40
+ let(:channel_name) { 'private-test_channel' }
41
+
42
+ it "should be able to disable read permission" do
43
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => auth_token(subject, channel_name, 'read' => false) }.to_json)
44
+ subject.should_not_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name })
45
+ Socky::Server::Channel.find_or_create(@application.name, channel_name).send_data({ 'event' => 'test_event', 'channel' => channel_name })
46
+ end
47
+
48
+ it "should be able to enable write pemission" do
49
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
50
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => auth_token(other_user, channel_name, 'write' => true) }.to_json)
51
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
52
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
53
+ end
54
+
55
+ it "should still send messages with read permission disabled" do
56
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
57
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'write' => true, 'auth' => auth_token(other_user, channel_name, 'read' => false, 'write' => true) }.to_json)
58
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
59
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
60
+ end
61
+
62
+ it "should still receive messages with write permission disabled" do
63
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => false, 'auth' => auth_token(subject, channel_name, 'write' => false) }.to_json)
64
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => auth_token(other_user, channel_name, 'write' => true) }.to_json)
65
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
66
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
67
+ end
68
+ end
69
+
70
+ context "presence channel" do
71
+ let(:channel_name) { 'presence-test_channel' }
72
+
73
+ it "should be able to disable read permission" do
74
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => auth_token(subject, channel_name, 'read' => false) }.to_json)
75
+ subject.should_not_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name })
76
+ Socky::Server::Channel.find_or_create(@application.name, channel_name).send_data({ 'event' => 'test_event', 'channel' => channel_name })
77
+ end
78
+
79
+ it "should still send messages with read permission disabled" do
80
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
81
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'write' => true, 'auth' => auth_token(other_user, channel_name, 'read' => false, 'write' => true) }.to_json)
82
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
83
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
84
+ end
85
+
86
+ it "should not receive members notification with read permission disabled" do
87
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'read' => false, 'auth' => auth_token(subject, channel_name, 'read' => false) }.to_json)
88
+ subject.should_not_receive(:send_data)
89
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(other_user, channel_name) }.to_json)
90
+ end
91
+
92
+ it "should be able to enable write pemission" do
93
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
94
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => auth_token(other_user, channel_name, 'write' => true) }.to_json)
95
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
96
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
97
+ end
98
+
99
+ it "should still receive messages with write permission disabled" do
100
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => false, 'auth' => auth_token(subject, channel_name, 'write' => false) }.to_json)
101
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'auth' => auth_token(other_user, channel_name, 'write' => true) }.to_json)
102
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
103
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
104
+ end
105
+
106
+ it "should still send members notification with write permission disabled" do
107
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
108
+ subject.should_receive(:send_data).with({ 'event' => 'socky:member:added', 'channel' => channel_name, 'connection_id' => other_user.connection.id, 'data' => {} })
109
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => false, 'auth' => auth_token(other_user, channel_name, 'write' => false) }.to_json)
110
+ end
111
+
112
+ it "should be able to enable hide permission" do
113
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
114
+ subject.should_not_receive(:send_data).with({ 'event' => 'socky:member:added', 'channel' => channel_name, 'connection_id' => other_user.connection.id, 'data' => {} })
115
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'hide' => true, 'auth' => auth_token(other_user, channel_name, 'hide' => true) }.to_json)
116
+ end
117
+
118
+ it "should still receive messages with hide permission enabled" do
119
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'hide' => true, 'auth' => auth_token(subject, channel_name, 'hide' => true) }.to_json)
120
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name })
121
+ Socky::Server::Channel.find_or_create(@application.name, channel_name).send_data({ 'event' => 'test_event', 'channel' => channel_name })
122
+ end
123
+
124
+ it "should be able to send messages whild hide permission is enabled" do
125
+ subject.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'auth' => auth_token(subject, channel_name) }.to_json)
126
+ other_user.on_message({}, { 'event' => 'socky:subscribe', 'channel' => channel_name, 'write' => true, 'hide' => true, 'auth' => auth_token(other_user, channel_name, 'write' => true, 'hide' => true) }.to_json)
127
+ subject.should_receive(:send_data).with({ 'event' => 'test_event', 'channel' => channel_name, 'data' => nil })
128
+ other_user.on_message({}, { 'event' => 'test_event', 'channel' => channel_name }.to_json)
129
+ end
130
+ end
131
+ end
132
+
133
+ end