socky-server 0.4.1 → 0.5.0.beta1

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