ably 0.8.8 → 0.8.9
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.
- 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
|