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.
- data/.gitignore +0 -4
- data/.travis.yml +6 -0
- data/CHANGELOG.md +11 -5
- data/Gemfile +2 -0
- data/README.md +47 -68
- data/Rakefile +5 -7
- data/config.ru +19 -0
- data/example/config.yml +4 -0
- data/lib/socky/server.rb +23 -0
- data/lib/socky/server/application.rb +51 -0
- data/lib/socky/server/channel.rb +30 -0
- data/lib/socky/server/channel/base.rb +80 -0
- data/lib/socky/server/channel/presence.rb +49 -0
- data/lib/socky/server/channel/private.rb +44 -0
- data/lib/socky/server/channel/public.rb +43 -0
- data/lib/socky/server/channel/stub.rb +17 -0
- data/lib/socky/server/config.rb +52 -0
- data/lib/socky/server/connection.rb +66 -0
- data/lib/socky/server/http.rb +95 -0
- data/lib/socky/server/logger.rb +24 -0
- data/lib/socky/server/message.rb +35 -0
- data/lib/socky/server/misc.rb +18 -0
- data/lib/socky/server/version.rb +5 -0
- data/lib/socky/server/websocket.rb +43 -0
- data/socky-server.gemspec +5 -7
- data/spec/fixtures/example_config.yml +3 -0
- data/spec/integration/ws_channels_spec.rb +144 -0
- data/spec/integration/ws_connection_spec.rb +48 -0
- data/spec/integration/ws_presence_spec.rb +118 -0
- data/spec/integration/ws_rights_spec.rb +133 -0
- data/spec/spec_helper.rb +24 -2
- data/spec/support/websocket_application.rb +14 -0
- data/spec/unit/socky/server/application_spec.rb +54 -0
- data/spec/unit/socky/server/config_spec.rb +50 -0
- data/spec/unit/socky/server/connection_spec.rb +67 -0
- data/spec/unit/socky/server/message_spec.rb +64 -0
- metadata +93 -126
- data/bin/socky +0 -5
- data/lib/em-websocket_hacks.rb +0 -15
- data/lib/socky.rb +0 -75
- data/lib/socky/connection.rb +0 -137
- data/lib/socky/connection/authentication.rb +0 -99
- data/lib/socky/connection/finders.rb +0 -67
- data/lib/socky/message.rb +0 -85
- data/lib/socky/misc.rb +0 -74
- data/lib/socky/net_request.rb +0 -27
- data/lib/socky/options.rb +0 -39
- data/lib/socky/options/config.rb +0 -79
- data/lib/socky/options/parser.rb +0 -93
- data/lib/socky/runner.rb +0 -95
- data/spec/em-websocket_spec.rb +0 -36
- data/spec/files/default.yml +0 -18
- data/spec/files/invalid.yml +0 -1
- data/spec/socky/connection/authentication_spec.rb +0 -183
- data/spec/socky/connection/finders_spec.rb +0 -188
- data/spec/socky/connection_spec.rb +0 -151
- data/spec/socky/message_spec.rb +0 -102
- data/spec/socky/misc_spec.rb +0 -74
- data/spec/socky/net_request_spec.rb +0 -42
- data/spec/socky/options/config_spec.rb +0 -72
- data/spec/socky/options/parser_spec.rb +0 -76
- data/spec/socky/options_spec.rb +0 -60
- data/spec/socky/runner_spec.rb +0 -88
- data/spec/socky_spec.rb +0 -89
- data/spec/support/stallion.rb +0 -96
data/socky-server.gemspec
CHANGED
@@ -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.
|
16
|
-
s.
|
17
|
-
s.
|
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,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
|