ably 0.8.8 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/LICENSE +2 -2
- data/README.md +81 -20
- data/SPEC.md +235 -178
- data/lib/ably/auth.rb +1 -1
- data/lib/ably/exceptions.rb +10 -1
- data/lib/ably/models/cipher_params.rb +114 -0
- data/lib/ably/models/connection_details.rb +8 -6
- data/lib/ably/models/error_info.rb +3 -3
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +27 -20
- data/lib/ably/models/message.rb +15 -15
- data/lib/ably/models/message_encoders/cipher.rb +8 -7
- data/lib/ably/models/presence_message.rb +17 -17
- data/lib/ably/models/protocol_message.rb +26 -19
- data/lib/ably/models/stats.rb +15 -15
- data/lib/ably/models/token_details.rb +14 -12
- data/lib/ably/models/token_request.rb +16 -14
- data/lib/ably/modules/async_wrapper.rb +1 -1
- data/lib/ably/modules/encodeable.rb +10 -10
- data/lib/ably/modules/model_common.rb +13 -5
- data/lib/ably/realtime/channel.rb +1 -2
- data/lib/ably/realtime/presence.rb +29 -58
- data/lib/ably/realtime/presence/members_map.rb +2 -2
- data/lib/ably/rest/channel.rb +1 -2
- data/lib/ably/rest/middleware/exceptions.rb +14 -4
- data/lib/ably/rest/presence.rb +3 -1
- data/lib/ably/util/crypto.rb +50 -40
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/message_spec.rb +20 -20
- data/spec/acceptance/realtime/presence_history_spec.rb +7 -7
- data/spec/acceptance/realtime/presence_spec.rb +65 -77
- data/spec/acceptance/rest/auth_spec.rb +8 -8
- data/spec/acceptance/rest/base_spec.rb +4 -4
- data/spec/acceptance/rest/channel_spec.rb +1 -1
- data/spec/acceptance/rest/client_spec.rb +1 -1
- data/spec/acceptance/rest/encoders_spec.rb +4 -4
- data/spec/acceptance/rest/message_spec.rb +15 -15
- data/spec/acceptance/rest/presence_spec.rb +4 -4
- data/spec/shared/model_behaviour.rb +7 -7
- data/spec/unit/models/cipher_params_spec.rb +140 -0
- data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +15 -8
- data/spec/unit/models/message_encoders/cipher_spec.rb +28 -22
- data/spec/unit/models/message_encoders/json_spec.rb +24 -0
- data/spec/unit/models/protocol_message_spec.rb +3 -3
- data/spec/unit/util/crypto_spec.rb +50 -17
- metadata +5 -2
@@ -3,7 +3,7 @@ require 'ably/models/message_encoders/cipher'
|
|
3
3
|
require 'msgpack'
|
4
4
|
|
5
5
|
describe Ably::Models::MessageEncoders::Cipher do
|
6
|
-
let(:secret_key) {
|
6
|
+
let(:secret_key) { Ably::Util::Crypto.generate_random_key(128) }
|
7
7
|
let(:crypto_options) { { key: secret_key, algorithm: 'AES', mode: 'CBC', key_length: 128 } }
|
8
8
|
let(:crypto) { Ably::Util::Crypto.new(cipher_params) }
|
9
9
|
|
@@ -23,7 +23,7 @@ describe Ably::Models::MessageEncoders::Cipher do
|
|
23
23
|
|
24
24
|
context 'valid cipher data' do
|
25
25
|
before do
|
26
|
-
subject.decode message, {
|
26
|
+
subject.decode message, { cipher: cipher_params }
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'message with cipher payload' do
|
@@ -79,29 +79,33 @@ describe Ably::Models::MessageEncoders::Cipher do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
context '
|
83
|
-
let(:
|
84
|
-
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
85
|
-
let(:decode_method) { subject.decode message, { encrypted: true, cipher_params: cipher_params } }
|
82
|
+
context '256 bit key' do
|
83
|
+
let(:secret_key) { Ably::Util::Crypto.generate_random_key(256) }
|
86
84
|
|
87
|
-
|
88
|
-
|
85
|
+
context 'with invalid channel_option cipher params' do
|
86
|
+
let(:message) { { data: decoded_data, encoding: 'cipher+aes-128-cbc' } }
|
87
|
+
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
88
|
+
let(:decode_method) { subject.decode message, { cipher: cipher_params } }
|
89
|
+
|
90
|
+
it 'raise an exception' do
|
91
|
+
expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /Cipher algorithm [\w-]+ does not match message cipher algorithm of AES-128-CBC/
|
92
|
+
end
|
89
93
|
end
|
90
|
-
end
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
95
|
+
context 'without any configured encryption' do
|
96
|
+
let(:message) { { data: decoded_data, encoding: 'cipher+aes-128-cbc' } }
|
97
|
+
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
98
|
+
let(:decode_method) { subject.decode message, {} }
|
96
99
|
|
97
|
-
|
98
|
-
|
100
|
+
it 'raise an exception' do
|
101
|
+
expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /Message cannot be decrypted as the channel is not set up for encryption & decryption/
|
102
|
+
end
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
102
106
|
context 'with invalid cipher data' do
|
103
107
|
let(:message) { { data: decoded_data, encoding: 'cipher+aes-128-cbc' } }
|
104
|
-
let(:decode_method) { subject.decode(message, {
|
108
|
+
let(:decode_method) { subject.decode(message, { cipher: cipher_params }) }
|
105
109
|
|
106
110
|
it 'raise an exception' do
|
107
111
|
expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /CipherError decrypting data/
|
@@ -110,10 +114,11 @@ describe Ably::Models::MessageEncoders::Cipher do
|
|
110
114
|
end
|
111
115
|
|
112
116
|
context 'with AES-256-CBC' do
|
117
|
+
let(:secret_key) { Ably::Util::Crypto.generate_random_key(256) }
|
113
118
|
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
114
119
|
|
115
120
|
before do
|
116
|
-
subject.decode message, {
|
121
|
+
subject.decode message, { cipher: cipher_params }
|
117
122
|
end
|
118
123
|
|
119
124
|
context 'message with cipher payload' do
|
@@ -133,7 +138,7 @@ describe Ably::Models::MessageEncoders::Cipher do
|
|
133
138
|
context '#encode' do
|
134
139
|
context 'with channel set up for AES-128-CBC' do
|
135
140
|
let(:cipher_params) { crypto_options }
|
136
|
-
let(:channel_options) { {
|
141
|
+
let(:channel_options) { { cipher: cipher_params } }
|
137
142
|
|
138
143
|
context 'with encrypted set to true' do
|
139
144
|
before do
|
@@ -211,12 +216,12 @@ describe Ably::Models::MessageEncoders::Cipher do
|
|
211
216
|
|
212
217
|
context 'channel_option cipher params' do
|
213
218
|
let(:message) { { data: decoded_data, encoding: nil } }
|
214
|
-
let(:encode_method) { subject.encode message, {
|
219
|
+
let(:encode_method) { subject.encode message, { cipher: cipher_params } }
|
215
220
|
|
216
221
|
context 'have invalid key length' do
|
217
222
|
let(:cipher_params) { crypto_options.merge(key_length: 1) }
|
218
223
|
it 'raise an exception' do
|
219
|
-
expect { encode_method }.to raise_error Ably::Exceptions::CipherError, /
|
224
|
+
expect { encode_method }.to raise_error Ably::Exceptions::CipherError, /Incompatible :key length/
|
220
225
|
end
|
221
226
|
end
|
222
227
|
|
@@ -230,17 +235,18 @@ describe Ably::Models::MessageEncoders::Cipher do
|
|
230
235
|
context 'have missing key' do
|
231
236
|
let(:cipher_params) { {} }
|
232
237
|
it 'raise an exception' do
|
233
|
-
expect { encode_method }.to raise_error Ably::Exceptions::CipherError,
|
238
|
+
expect { encode_method }.to raise_error Ably::Exceptions::CipherError, /key.*required/
|
234
239
|
end
|
235
240
|
end
|
236
241
|
end
|
237
242
|
end
|
238
243
|
|
239
244
|
context 'with AES-256-CBC' do
|
245
|
+
let(:secret_key) { Ably::Util::Crypto.generate_random_key(256) }
|
240
246
|
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
241
247
|
|
242
248
|
before do
|
243
|
-
subject.encode message, {
|
249
|
+
subject.encode message, { cipher: cipher_params }
|
244
250
|
end
|
245
251
|
|
246
252
|
context 'message with cipher payload' do
|
@@ -30,6 +30,18 @@ describe Ably::Models::MessageEncoders::Json do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
context 'message with json payload in camelCase' do
|
34
|
+
let(:message) { { data: '{"keyId":"test"}', encoding: 'json' } }
|
35
|
+
|
36
|
+
it 'decodes json' do
|
37
|
+
expect(message[:data]).to eq({ 'keyId' => 'test' })
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'strips the encoding' do
|
41
|
+
expect(message[:encoding]).to be_nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
33
45
|
context 'message with json payload before other payloads' do
|
34
46
|
let(:message) { { data: hash_string_data, encoding: 'utf-8/json' } }
|
35
47
|
|
@@ -72,6 +84,18 @@ describe Ably::Models::MessageEncoders::Json do
|
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
87
|
+
context 'message with hash payload and underscore case keys' do
|
88
|
+
let(:message) { { data: { key_id: 'test' }, encoding: nil } }
|
89
|
+
|
90
|
+
it 'encodes hash payload data as json and leaves underscore case in tact' do
|
91
|
+
expect(message[:data]).to eql('{"key_id":"test"}')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'adds the encoding' do
|
95
|
+
expect(message[:encoding]).to eql('json')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
75
99
|
context 'already encoded message with hash payload' do
|
76
100
|
let(:message) { { data: hash_data, encoding: 'utf-8' } }
|
77
101
|
|
@@ -20,17 +20,17 @@ describe Ably::Models::ProtocolMessage do
|
|
20
20
|
context 'initializer action coercion', :api_private do
|
21
21
|
it 'ignores actions that are Integers' do
|
22
22
|
protocol_message = subject.new(action: 14)
|
23
|
-
expect(protocol_message.
|
23
|
+
expect(protocol_message.attributes[:action]).to eql(14)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'converts actions to Integers if a symbol' do
|
27
27
|
protocol_message = subject.new(action: :message)
|
28
|
-
expect(protocol_message.
|
28
|
+
expect(protocol_message.attributes[:action]).to eql(15)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'converts actions to Integers if a ACTION' do
|
32
32
|
protocol_message = subject.new(action: Ably::Models::ProtocolMessage::ACTION.Message)
|
33
|
-
expect(protocol_message.
|
33
|
+
expect(protocol_message.attributes[:action]).to eql(15)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'raises an argument error if nil' do
|
@@ -2,16 +2,17 @@ require 'spec_helper'
|
|
2
2
|
require 'msgpack'
|
3
3
|
|
4
4
|
describe Ably::Util::Crypto do
|
5
|
-
let(:
|
6
|
-
let(:
|
5
|
+
let(:cipher) { OpenSSL::Cipher.new('AES-256-CBC') }
|
6
|
+
let(:secret_key) { cipher.random_key }
|
7
|
+
let(:cipher_options) { { key: secret_key } }
|
7
8
|
subject { Ably::Util::Crypto.new(cipher_options) }
|
8
9
|
|
9
10
|
context 'defaults' do
|
10
11
|
let(:expected_defaults) do
|
11
12
|
{
|
12
|
-
algorithm: '
|
13
|
-
mode: '
|
14
|
-
key_length:
|
13
|
+
algorithm: 'aes',
|
14
|
+
mode: 'cbc',
|
15
|
+
key_length: 256
|
15
16
|
}
|
16
17
|
end
|
17
18
|
|
@@ -22,20 +23,52 @@ describe Ably::Util::Crypto do
|
|
22
23
|
end
|
23
24
|
|
24
25
|
context 'get_default_params' do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
context 'with just a :key param' do
|
27
|
+
let(:defaults) { Ably::Util::Crypto.get_default_params(key: secret_key) }
|
28
|
+
|
29
|
+
it 'uses the defaults' do
|
30
|
+
expect(defaults.algorithm).to eql('aes')
|
31
|
+
expect(defaults.mode).to eql('cbc')
|
32
|
+
expect(defaults.key_length).to eql(256)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'contains the provided key' do
|
36
|
+
expect(defaults.key).to eql(secret_key)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns a CipherParams object' do
|
40
|
+
expect(defaults).to be_a(Ably::Models::CipherParams)
|
41
|
+
end
|
30
42
|
end
|
31
43
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
context 'without a :key param' do
|
45
|
+
let(:cipher_params) { Ably::Util::Crypto.get_default_params }
|
46
|
+
|
47
|
+
it 'raises an exception' do
|
48
|
+
expect { cipher_params }.to raise_error(/key.*required/)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with a base64-encoded :key param' do
|
53
|
+
let(:cipher_params) { Ably::Util::Crypto.get_default_params(key: Base64.encode64(secret_key)) }
|
54
|
+
|
55
|
+
it 'converts the key to binary' do
|
56
|
+
expect(cipher_params.key).to eql(secret_key)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with provided params' do
|
61
|
+
let(:algorithm) { 'FOO' }
|
62
|
+
let(:mode) { 'BAR' }
|
63
|
+
let(:key_length) { 192 }
|
64
|
+
let(:key) { secret_key[0...24] }
|
65
|
+
let(:cipher_params) { Ably::Util::Crypto.get_default_params(key: key, algorithm: algorithm, mode: mode, key_length: key_length) }
|
66
|
+
|
67
|
+
it 'overrides the defaults' do
|
68
|
+
expect(cipher_params.algorithm).to eql('foo')
|
69
|
+
expect(cipher_params.mode).to eql('bar')
|
70
|
+
expect(cipher_params.key_length).to eql(192)
|
71
|
+
end
|
39
72
|
end
|
40
73
|
end
|
41
74
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ably
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lewis Marshall
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-01
|
12
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -287,6 +287,7 @@ files:
|
|
287
287
|
- lib/ably/exceptions.rb
|
288
288
|
- lib/ably/logger.rb
|
289
289
|
- lib/ably/models/channel_state_change.rb
|
290
|
+
- lib/ably/models/cipher_params.rb
|
290
291
|
- lib/ably/models/connection_details.rb
|
291
292
|
- lib/ably/models/connection_state_change.rb
|
292
293
|
- lib/ably/models/error_info.rb
|
@@ -397,6 +398,7 @@ files:
|
|
397
398
|
- spec/unit/auth_spec.rb
|
398
399
|
- spec/unit/logger_spec.rb
|
399
400
|
- spec/unit/models/channel_state_change_spec.rb
|
401
|
+
- spec/unit/models/cipher_params_spec.rb
|
400
402
|
- spec/unit/models/connection_details_spec.rb
|
401
403
|
- spec/unit/models/connection_state_change_spec.rb
|
402
404
|
- spec/unit/models/error_info_spec.rb
|
@@ -497,6 +499,7 @@ test_files:
|
|
497
499
|
- spec/unit/auth_spec.rb
|
498
500
|
- spec/unit/logger_spec.rb
|
499
501
|
- spec/unit/models/channel_state_change_spec.rb
|
502
|
+
- spec/unit/models/cipher_params_spec.rb
|
500
503
|
- spec/unit/models/connection_details_spec.rb
|
501
504
|
- spec/unit/models/connection_state_change_spec.rb
|
502
505
|
- spec/unit/models/error_info_spec.rb
|