ably 0.8.8 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -2
  3. data/LICENSE +2 -2
  4. data/README.md +81 -20
  5. data/SPEC.md +235 -178
  6. data/lib/ably/auth.rb +1 -1
  7. data/lib/ably/exceptions.rb +10 -1
  8. data/lib/ably/models/cipher_params.rb +114 -0
  9. data/lib/ably/models/connection_details.rb +8 -6
  10. data/lib/ably/models/error_info.rb +3 -3
  11. data/lib/ably/models/idiomatic_ruby_wrapper.rb +27 -20
  12. data/lib/ably/models/message.rb +15 -15
  13. data/lib/ably/models/message_encoders/cipher.rb +8 -7
  14. data/lib/ably/models/presence_message.rb +17 -17
  15. data/lib/ably/models/protocol_message.rb +26 -19
  16. data/lib/ably/models/stats.rb +15 -15
  17. data/lib/ably/models/token_details.rb +14 -12
  18. data/lib/ably/models/token_request.rb +16 -14
  19. data/lib/ably/modules/async_wrapper.rb +1 -1
  20. data/lib/ably/modules/encodeable.rb +10 -10
  21. data/lib/ably/modules/model_common.rb +13 -5
  22. data/lib/ably/realtime/channel.rb +1 -2
  23. data/lib/ably/realtime/presence.rb +29 -58
  24. data/lib/ably/realtime/presence/members_map.rb +2 -2
  25. data/lib/ably/rest/channel.rb +1 -2
  26. data/lib/ably/rest/middleware/exceptions.rb +14 -4
  27. data/lib/ably/rest/presence.rb +3 -1
  28. data/lib/ably/util/crypto.rb +50 -40
  29. data/lib/ably/version.rb +1 -1
  30. data/spec/acceptance/realtime/message_spec.rb +20 -20
  31. data/spec/acceptance/realtime/presence_history_spec.rb +7 -7
  32. data/spec/acceptance/realtime/presence_spec.rb +65 -77
  33. data/spec/acceptance/rest/auth_spec.rb +8 -8
  34. data/spec/acceptance/rest/base_spec.rb +4 -4
  35. data/spec/acceptance/rest/channel_spec.rb +1 -1
  36. data/spec/acceptance/rest/client_spec.rb +1 -1
  37. data/spec/acceptance/rest/encoders_spec.rb +4 -4
  38. data/spec/acceptance/rest/message_spec.rb +15 -15
  39. data/spec/acceptance/rest/presence_spec.rb +4 -4
  40. data/spec/shared/model_behaviour.rb +7 -7
  41. data/spec/unit/models/cipher_params_spec.rb +140 -0
  42. data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +15 -8
  43. data/spec/unit/models/message_encoders/cipher_spec.rb +28 -22
  44. data/spec/unit/models/message_encoders/json_spec.rb +24 -0
  45. data/spec/unit/models/protocol_message_spec.rb +3 -3
  46. data/spec/unit/util/crypto_spec.rb +50 -17
  47. 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) { random_str(64) }
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, { encrypted: true, cipher_params: cipher_params }
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 'with invalid channel_option cipher params' do
83
- let(:message) { { data: decoded_data, encoding: 'cipher+aes-128-cbc' } }
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
- it 'raise an exception' do
88
- expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /Cipher algorithm [\w-]+ does not match message cipher algorithm of AES-128-CBC/
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
- context 'without any configured encryption' do
93
- let(:message) { { data: decoded_data, encoding: 'cipher+aes-128-cbc' } }
94
- let(:cipher_params) { crypto_options.merge(key_length: 256) }
95
- let(:decode_method) { subject.decode message, {} }
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
- it 'raise an exception' do
98
- expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /Message cannot be decrypted as the channel is not set up for encryption & decryption/
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, { encrypted: true, cipher_params: cipher_params }) }
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, { encrypted: true, cipher_params: cipher_params }
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) { { encrypted: true, cipher_params: cipher_params } }
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, { encrypted: true, cipher_params: cipher_params } }
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, /unsupported cipher algorithm/
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, /:key is required/
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, { encrypted: true, cipher_params: cipher_params }
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.hash[:action]).to eql(14)
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.hash[:action]).to eql(15)
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.hash[:action]).to eql(15)
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(:seret_key) { random_str }
6
- let(:cipher_options) { { key: seret_key } }
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: 'AES',
13
- mode: 'CBC',
14
- key_length: 128
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
- it 'uses the defaults and generates a key if not provided' do
26
- expect(Ably::Util::Crypto.get_default_params[:algorithm]).to eql('AES')
27
- expect(Ably::Util::Crypto.get_default_params[:mode]).to eql('CBC')
28
- expect(Ably::Util::Crypto.get_default_params[:key_length]).to eql(128)
29
- expect(Ably::Util::Crypto.get_default_params[:key].unpack('b*').first.length).to eql(128)
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
- it 'uses the defaults and sets the key size when key is provided' do
33
- key_192 = '123456781234567812345678'
34
- params = Ably::Util::Crypto.get_default_params(key_192)
35
- expect(params[:algorithm]).to eql('AES')
36
- expect(params[:mode]).to eql('CBC')
37
- expect(params[:key_length]).to eql(192)
38
- expect(params[:key]).to eql(key_192)
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.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-26 00:00:00.000000000 Z
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