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.
- 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
|