ably 0.1.6 → 0.2.0
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/.gitignore +2 -0
- data/.travis.yml +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +8 -1
- data/Rakefile +10 -0
- data/ably.gemspec +18 -18
- data/lib/ably.rb +6 -5
- data/lib/ably/auth.rb +11 -14
- data/lib/ably/exceptions.rb +18 -15
- data/lib/ably/logger.rb +102 -0
- data/lib/ably/models/error_info.rb +1 -1
- data/lib/ably/models/message.rb +19 -5
- data/lib/ably/models/message_encoders/base.rb +107 -0
- data/lib/ably/models/message_encoders/base64.rb +39 -0
- data/lib/ably/models/message_encoders/cipher.rb +80 -0
- data/lib/ably/models/message_encoders/json.rb +33 -0
- data/lib/ably/models/message_encoders/utf8.rb +33 -0
- data/lib/ably/models/paginated_resource.rb +23 -6
- data/lib/ably/models/presence_message.rb +19 -7
- data/lib/ably/models/protocol_message.rb +5 -4
- data/lib/ably/models/token.rb +2 -2
- data/lib/ably/modules/channels_collection.rb +0 -3
- data/lib/ably/modules/conversions.rb +3 -3
- data/lib/ably/modules/encodeable.rb +68 -0
- data/lib/ably/modules/event_emitter.rb +10 -4
- data/lib/ably/modules/event_machine_helpers.rb +6 -4
- data/lib/ably/modules/http_helpers.rb +7 -2
- data/lib/ably/modules/model_common.rb +2 -0
- data/lib/ably/modules/state_emitter.rb +10 -1
- data/lib/ably/realtime.rb +19 -12
- data/lib/ably/realtime/channel.rb +26 -13
- data/lib/ably/realtime/client.rb +31 -7
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -3
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +13 -4
- data/lib/ably/realtime/connection.rb +152 -46
- data/lib/ably/realtime/connection/connection_manager.rb +168 -0
- data/lib/ably/realtime/connection/connection_state_machine.rb +56 -33
- data/lib/ably/realtime/connection/websocket_transport.rb +56 -29
- data/lib/ably/{models → realtime/models}/nil_channel.rb +1 -1
- data/lib/ably/realtime/presence.rb +38 -13
- data/lib/ably/rest.rb +7 -5
- data/lib/ably/rest/channel.rb +24 -3
- data/lib/ably/rest/client.rb +56 -17
- data/lib/ably/rest/middleware/encoder.rb +49 -0
- data/lib/ably/rest/middleware/exceptions.rb +3 -2
- data/lib/ably/rest/middleware/logger.rb +37 -0
- data/lib/ably/rest/presence.rb +10 -2
- data/lib/ably/util/crypto.rb +57 -29
- data/lib/ably/util/pub_sub.rb +11 -0
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_spec.rb +65 -7
- data/spec/acceptance/realtime/connection_spec.rb +123 -27
- data/spec/acceptance/realtime/message_spec.rb +319 -34
- data/spec/acceptance/realtime/presence_history_spec.rb +58 -0
- data/spec/acceptance/realtime/presence_spec.rb +160 -18
- data/spec/acceptance/rest/auth_spec.rb +93 -49
- data/spec/acceptance/rest/base_spec.rb +10 -10
- data/spec/acceptance/rest/channel_spec.rb +35 -19
- data/spec/acceptance/rest/channels_spec.rb +8 -8
- data/spec/acceptance/rest/message_spec.rb +224 -0
- data/spec/acceptance/rest/presence_spec.rb +159 -23
- data/spec/acceptance/rest/stats_spec.rb +5 -5
- data/spec/acceptance/rest/time_spec.rb +4 -4
- data/spec/integration/rest/auth.rb +1 -1
- data/spec/resources/crypto-data-128.json +56 -0
- data/spec/resources/crypto-data-256.json +56 -0
- data/spec/rspec_config.rb +39 -0
- data/spec/spec_helper.rb +4 -42
- data/spec/support/api_helper.rb +1 -1
- data/spec/support/event_machine_helper.rb +0 -5
- data/spec/support/protocol_msgbus_helper.rb +3 -3
- data/spec/support/test_app.rb +3 -3
- data/spec/unit/logger_spec.rb +135 -0
- data/spec/unit/models/message_encoders/base64_spec.rb +181 -0
- data/spec/unit/models/message_encoders/cipher_spec.rb +260 -0
- data/spec/unit/models/message_encoders/json_spec.rb +135 -0
- data/spec/unit/models/message_encoders/utf8_spec.rb +100 -0
- data/spec/unit/models/message_spec.rb +16 -1
- data/spec/unit/models/paginated_resource_spec.rb +46 -0
- data/spec/unit/models/presence_message_spec.rb +18 -5
- data/spec/unit/models/token_spec.rb +1 -1
- data/spec/unit/modules/event_emitter_spec.rb +24 -10
- data/spec/unit/realtime/channel_spec.rb +3 -3
- data/spec/unit/realtime/channels_spec.rb +1 -1
- data/spec/unit/realtime/client_spec.rb +44 -2
- data/spec/unit/realtime/connection_spec.rb +2 -2
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +4 -4
- data/spec/unit/realtime/presence_spec.rb +1 -1
- data/spec/unit/realtime/realtime_spec.rb +3 -3
- data/spec/unit/realtime/websocket_transport_spec.rb +24 -0
- data/spec/unit/rest/channels_spec.rb +1 -1
- data/spec/unit/rest/client_spec.rb +45 -10
- data/spec/unit/util/crypto_spec.rb +82 -0
- data/spec/unit/{modules → util}/pub_sub_spec.rb +13 -1
- metadata +43 -12
- data/spec/acceptance/crypto.rb +0 -63
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'base64'
|
3
|
+
require 'msgpack'
|
4
|
+
|
5
|
+
require 'ably/models/message_encoders/base64'
|
6
|
+
|
7
|
+
describe Ably::Models::MessageEncoders::Base64 do
|
8
|
+
let(:decoded_data) { SecureRandom.hex(32) }
|
9
|
+
let(:base64_data) { Base64.encode64(decoded_data) }
|
10
|
+
let(:binary_data) { MessagePack.pack(decoded_data) }
|
11
|
+
let(:base64_binary_data) { Base64.encode64(binary_data) }
|
12
|
+
let(:client) { instance_double('Ably::Realtime::Client') }
|
13
|
+
|
14
|
+
subject { Ably::Models::MessageEncoders::Base64.new(client) }
|
15
|
+
|
16
|
+
context '#decode' do
|
17
|
+
before do
|
18
|
+
subject.decode message, {}
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'message with base64 payload' do
|
22
|
+
let(:message) { { data: base64_data, encoding: 'base64' } }
|
23
|
+
|
24
|
+
it 'decodes base64' do
|
25
|
+
expect(message[:data]).to eql(decoded_data)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'strips the encoding' do
|
29
|
+
expect(message[:encoding]).to be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'message with base64 payload before other payloads' do
|
34
|
+
let(:message) { { data: base64_data, encoding: 'utf-8/base64' } }
|
35
|
+
|
36
|
+
it 'decodes base64' do
|
37
|
+
expect(message[:data]).to eql(decoded_data)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'strips the encoding' do
|
41
|
+
expect(message[:encoding]).to eql('utf-8')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'message with another payload' do
|
46
|
+
let(:message) { { data: decoded_data, encoding: 'utf-8' } }
|
47
|
+
|
48
|
+
it 'leaves the message data intact' do
|
49
|
+
expect(message[:data]).to eql(decoded_data)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'leaves the encoding intact' do
|
53
|
+
expect(message[:encoding]).to eql('utf-8')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context '#encode' do
|
59
|
+
context 'over binary transport' do
|
60
|
+
before do
|
61
|
+
allow(client).to receive(:protocol_binary?).and_return(true)
|
62
|
+
subject.encode message, {}
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'message with binary payload' do
|
66
|
+
let(:message) { { data: binary_data, encoding: nil } }
|
67
|
+
|
68
|
+
it 'leaves the message data intact as Base64 encoding is not necessary' do
|
69
|
+
expect(message[:data]).to eql(binary_data)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'leaves the encoding intact' do
|
73
|
+
expect(message[:encoding]).to eql(nil)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'already encoded message with binary payload' do
|
78
|
+
let(:message) { { data: binary_data, encoding: 'cipher' } }
|
79
|
+
|
80
|
+
it 'leaves the message data intact as Base64 encoding is not necessary' do
|
81
|
+
expect(message[:data]).to eql(binary_data)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'leaves the encoding intact' do
|
85
|
+
expect(message[:encoding]).to eql('cipher')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'message with UTF-8 payload' do
|
90
|
+
let(:message) { { data: decoded_data, encoding: nil } }
|
91
|
+
|
92
|
+
it 'leaves the data intact' do
|
93
|
+
expect(message[:data]).to eql(decoded_data)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'leaves the encoding intact' do
|
97
|
+
expect(message[:encoding]).to be_nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'message with nil payload' do
|
102
|
+
let(:message) { { data: nil, encoding: nil } }
|
103
|
+
|
104
|
+
it 'leaves the message data intact' do
|
105
|
+
expect(message[:data]).to be_nil
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'leaves the encoding intact' do
|
109
|
+
expect(message[:encoding]).to be_nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'message with empty binary string payload' do
|
114
|
+
let(:message) { { data: ''.force_encoding(Encoding::ASCII_8BIT), encoding: nil } }
|
115
|
+
|
116
|
+
it 'leaves the message data intact' do
|
117
|
+
expect(message[:data]).to eql('')
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'leaves the encoding intact' do
|
121
|
+
expect(message[:encoding]).to be_nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'over text transport' do
|
127
|
+
before do
|
128
|
+
allow(client).to receive(:protocol_binary?).and_return(false)
|
129
|
+
subject.encode message, {}
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'message with binary payload' do
|
133
|
+
let(:message) { { data: binary_data, encoding: nil } }
|
134
|
+
|
135
|
+
it 'encodes binary data as base64' do
|
136
|
+
expect(message[:data]).to eql(base64_binary_data)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'adds the encoding' do
|
140
|
+
expect(message[:encoding]).to eql('base64')
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'already encoded message with binary payload' do
|
145
|
+
let(:message) { { data: binary_data, encoding: 'cipher' } }
|
146
|
+
|
147
|
+
it 'encodes binary data as base64' do
|
148
|
+
expect(message[:data]).to eql(base64_binary_data)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'adds the encoding' do
|
152
|
+
expect(message[:encoding]).to eql('cipher/base64')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'message with UTF-8 payload' do
|
157
|
+
let(:message) { { data: decoded_data, encoding: nil } }
|
158
|
+
|
159
|
+
it 'leaves the data intact' do
|
160
|
+
expect(message[:data]).to eql(decoded_data)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'leaves the encoding intact' do
|
164
|
+
expect(message[:encoding]).to be_nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'message with nil payload' do
|
169
|
+
let(:message) { { data: nil, encoding: nil } }
|
170
|
+
|
171
|
+
it 'leaves the message data intact' do
|
172
|
+
expect(message[:data]).to be_nil
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'leaves the encoding intact' do
|
176
|
+
expect(message[:encoding]).to be_nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ably/models/message_encoders/cipher'
|
3
|
+
require 'msgpack'
|
4
|
+
|
5
|
+
describe Ably::Models::MessageEncoders::Cipher do
|
6
|
+
let(:secret_key) { SecureRandom.hex(64) }
|
7
|
+
let(:crypto_options) { { key: secret_key, algorithm: 'AES', mode: 'CBC', key_length: 128 } }
|
8
|
+
let(:crypto) { Ably::Util::Crypto.new(cipher_params) }
|
9
|
+
|
10
|
+
let(:decoded_data) { SecureRandom.hex(32) }
|
11
|
+
let(:cipher_data) { crypto.encrypt(decoded_data) }
|
12
|
+
|
13
|
+
let(:binary_data) { MessagePack.pack(decoded_data) }
|
14
|
+
let(:binary_cipher_data) { crypto.encrypt(binary_data) }
|
15
|
+
|
16
|
+
let(:client) { instance_double('Ably::Realtime::Client') }
|
17
|
+
|
18
|
+
subject { Ably::Models::MessageEncoders::Cipher.new(client) }
|
19
|
+
|
20
|
+
context '#decode' do
|
21
|
+
context 'with channel set up for AES-128-CBC' do
|
22
|
+
let(:cipher_params) { crypto_options }
|
23
|
+
|
24
|
+
context 'valid cipher data' do
|
25
|
+
before do
|
26
|
+
subject.decode message, { encrypted: true, cipher_params: cipher_params }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'message with cipher payload' do
|
30
|
+
let(:message) { { data: cipher_data, encoding: 'cipher+aes-128-cbc' } }
|
31
|
+
|
32
|
+
it 'decodes cipher' do
|
33
|
+
expect(message[:data]).to eql(decoded_data)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'strips the encoding' do
|
37
|
+
expect(message[:encoding]).to be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'message with cipher payload before other payloads' do
|
42
|
+
let(:message) { { data: cipher_data, encoding: 'utf-8/cipher+aes-128-cbc' } }
|
43
|
+
|
44
|
+
it 'decodes cipher' do
|
45
|
+
expect(message[:data]).to eql(decoded_data)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'strips the encoding' do
|
49
|
+
expect(message[:encoding]).to eql('utf-8')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'message with binary payload' do
|
54
|
+
let(:message) { { data: binary_cipher_data, encoding: 'base64/cipher+aes-128-cbc' } }
|
55
|
+
|
56
|
+
it 'decodes cipher' do
|
57
|
+
expect(message[:data]).to eql(binary_data)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'strips the encoding' do
|
61
|
+
expect(message[:encoding]).to eql('base64')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns ASCII_8BIT encoded binary data' do
|
65
|
+
expect(message[:data].encoding).to eql(Encoding::ASCII_8BIT)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'message with another payload' do
|
70
|
+
let(:message) { { data: decoded_data, encoding: 'utf-8' } }
|
71
|
+
|
72
|
+
it 'leaves the message data intact' do
|
73
|
+
expect(message[:data]).to eql(decoded_data)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'leaves the encoding intact' do
|
77
|
+
expect(message[:encoding]).to eql('utf-8')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
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 } }
|
86
|
+
|
87
|
+
it 'raise an exception' do
|
88
|
+
expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /Cipher algorithm [\w\d-]+ does not match message cipher algorithm of AES-128-CBC/
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
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, {} }
|
96
|
+
|
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/
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'with invalid cipher data' do
|
103
|
+
let(:message) { { data: decoded_data, encoding: 'cipher+aes-128-cbc' } }
|
104
|
+
let(:decode_method) { subject.decode(message, { encrypted: true, cipher_params: cipher_params }) }
|
105
|
+
|
106
|
+
it 'raise an exception' do
|
107
|
+
expect { decode_method }.to raise_error Ably::Exceptions::CipherError, /CipherError decrypting data/
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'with AES-256-CBC' do
|
113
|
+
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
114
|
+
|
115
|
+
before do
|
116
|
+
subject.decode message, { encrypted: true, cipher_params: cipher_params }
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'message with cipher payload' do
|
120
|
+
let(:message) { { data: cipher_data, encoding: 'cipher+aes-256-cbc' } }
|
121
|
+
|
122
|
+
it 'decodes cipher' do
|
123
|
+
expect(message[:data]).to eql(decoded_data)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'strips the encoding' do
|
127
|
+
expect(message[:encoding]).to be_nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context '#encode' do
|
134
|
+
context 'with channel set up for AES-128-CBC' do
|
135
|
+
let(:cipher_params) { crypto_options }
|
136
|
+
let(:channel_options) { { encrypted: true, cipher_params: cipher_params } }
|
137
|
+
|
138
|
+
context 'with encrypted set to true' do
|
139
|
+
before do
|
140
|
+
subject.encode message, channel_options
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'message with string payload' do
|
144
|
+
let(:message) { { data: decoded_data, encoding: nil } }
|
145
|
+
|
146
|
+
it 'encodes cipher' do
|
147
|
+
expect(message[:data]).to_not eql(decoded_data)
|
148
|
+
expect(crypto.decrypt(message[:data])).to eql(decoded_data)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'adds the encoding with utf-8' do
|
152
|
+
expect(message[:encoding]).to eql('utf-8/cipher+aes-128-cbc')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'message with binary payload' do
|
157
|
+
let(:message) { { data: binary_data, encoding: nil } }
|
158
|
+
|
159
|
+
it 'encodes cipher' do
|
160
|
+
expect(message[:data]).to_not eql(binary_data)
|
161
|
+
expect(crypto.decrypt(message[:data])).to eql(binary_data)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'adds the encoding without utf-8 prefixed' do
|
165
|
+
expect(message[:encoding]).to eql('cipher+aes-128-cbc')
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'returns ASCII_8BIT encoded binary data' do
|
169
|
+
expect(message[:data].encoding).to eql(Encoding::ASCII_8BIT)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'message with json payload' do
|
174
|
+
let(:message) { { data: decoded_data, encoding: 'json' } }
|
175
|
+
|
176
|
+
it 'encodes cipher' do
|
177
|
+
expect(message[:data]).to_not eql(decoded_data)
|
178
|
+
expect(crypto.decrypt(message[:data])).to eql(decoded_data)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'adds the encoding with utf-8' do
|
182
|
+
expect(message[:encoding]).to eql('json/utf-8/cipher+aes-128-cbc')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'message with existing cipher encoding before' do
|
187
|
+
let(:message) { { data: decoded_data, encoding: 'utf-8/cipher+aes-128-cbc' } }
|
188
|
+
|
189
|
+
it 'leaves message intact as it is already encrypted' do
|
190
|
+
expect(message[:data]).to eql(decoded_data)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'leaves encoding intact' do
|
194
|
+
expect(message[:encoding]).to eql('utf-8/cipher+aes-128-cbc')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'with encryption set to to false' do
|
199
|
+
let(:message) { { data: decoded_data, encoding: 'utf-8' } }
|
200
|
+
let(:channel_options) { { encrypted: false, cipher_params: cipher_params } }
|
201
|
+
|
202
|
+
it 'leaves message intact as encryption is not enable' do
|
203
|
+
expect(message[:data]).to eql(decoded_data)
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'leaves encoding intact' do
|
207
|
+
expect(message[:encoding]).to eql('utf-8')
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context 'channel_option cipher params' do
|
213
|
+
let(:message) { { data: decoded_data, encoding: nil } }
|
214
|
+
let(:encode_method) { subject.encode message, { encrypted: true, cipher_params: cipher_params } }
|
215
|
+
|
216
|
+
context 'have invalid key length' do
|
217
|
+
let(:cipher_params) { crypto_options.merge(key_length: 1) }
|
218
|
+
it 'raise an exception' do
|
219
|
+
expect { encode_method }.to raise_error Ably::Exceptions::CipherError, /unsupported cipher algorithm/
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'have invalid algorithm' do
|
224
|
+
let(:cipher_params) { crypto_options.merge(algorithm: 'does not exist') }
|
225
|
+
it 'raise an exception' do
|
226
|
+
expect { encode_method }.to raise_error Ably::Exceptions::CipherError, /unsupported cipher algorithm/
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context 'have missing key' do
|
231
|
+
let(:cipher_params) { {} }
|
232
|
+
it 'raise an exception' do
|
233
|
+
expect { encode_method }.to raise_error Ably::Exceptions::CipherError, /:key is required/
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'with AES-256-CBC' do
|
240
|
+
let(:cipher_params) { crypto_options.merge(key_length: 256) }
|
241
|
+
|
242
|
+
before do
|
243
|
+
subject.encode message, { encrypted: true, cipher_params: cipher_params }
|
244
|
+
end
|
245
|
+
|
246
|
+
context 'message with cipher payload' do
|
247
|
+
let(:message) { { data: decoded_data, encoding: 'utf-8' } }
|
248
|
+
|
249
|
+
it 'decodes cipher' do
|
250
|
+
expect(message[:data]).to_not eql(decoded_data)
|
251
|
+
expect(crypto.decrypt(message[:data])).to eql(decoded_data)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'strips the encoding' do
|
255
|
+
expect(message[:encoding]).to eql('utf-8/cipher+aes-256-cbc')
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'ably/models/message_encoders/json'
|
5
|
+
|
6
|
+
describe Ably::Models::MessageEncoders::Json do
|
7
|
+
let(:hash_data) { { 'key' => 'value', 'key2' => 123 } }
|
8
|
+
let(:hash_string_data) { JSON.dump(hash_data) }
|
9
|
+
let(:array_data) { ['value', 123] }
|
10
|
+
let(:array_string_data) { JSON.dump(array_data) }
|
11
|
+
|
12
|
+
let(:client) { instance_double('Ably::Realtime::Client') }
|
13
|
+
|
14
|
+
subject { Ably::Models::MessageEncoders::Json.new(client) }
|
15
|
+
|
16
|
+
context '#decode' do
|
17
|
+
before do
|
18
|
+
subject.decode message, {}
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'message with json payload' do
|
22
|
+
let(:message) { { data: hash_string_data, encoding: 'json' } }
|
23
|
+
|
24
|
+
it 'decodes json' do
|
25
|
+
expect(message[:data]).to eq(hash_data)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'strips the encoding' do
|
29
|
+
expect(message[:encoding]).to be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'message with json payload before other payloads' do
|
34
|
+
let(:message) { { data: hash_string_data, encoding: 'utf-8/json' } }
|
35
|
+
|
36
|
+
it 'decodes json' do
|
37
|
+
expect(message[:data]).to eql(hash_data)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'strips the encoding' do
|
41
|
+
expect(message[:encoding]).to eql('utf-8')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'message with another payload' do
|
46
|
+
let(:message) { { data: hash_string_data, encoding: 'utf-8' } }
|
47
|
+
|
48
|
+
it 'leaves the message data intact' do
|
49
|
+
expect(message[:data]).to eql(hash_string_data)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'leaves the encoding intact' do
|
53
|
+
expect(message[:encoding]).to eql('utf-8')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context '#encode' do
|
59
|
+
before do
|
60
|
+
subject.encode message, {}
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'message with hash payload' do
|
64
|
+
let(:message) { { data: hash_data, encoding: nil } }
|
65
|
+
|
66
|
+
it 'encodes hash payload data as json' do
|
67
|
+
expect(message[:data]).to eql(hash_string_data)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'adds the encoding' do
|
71
|
+
expect(message[:encoding]).to eql('json')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'already encoded message with hash payload' do
|
76
|
+
let(:message) { { data: hash_data, encoding: 'utf-8' } }
|
77
|
+
|
78
|
+
it 'encodes hash payload data as json' do
|
79
|
+
expect(message[:data]).to eql(hash_string_data)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'adds the encoding' do
|
83
|
+
expect(message[:encoding]).to eql('utf-8/json')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'message with Array payload' do
|
88
|
+
let(:message) { { data: array_data, encoding: nil } }
|
89
|
+
|
90
|
+
it 'encodes Array payload data as json' do
|
91
|
+
expect(message[:data]).to eql(array_string_data)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'adds the encoding' do
|
95
|
+
expect(message[:encoding]).to eql('json')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'message with UTF-8 payload' do
|
100
|
+
let(:message) { { data: hash_string_data, encoding: nil } }
|
101
|
+
|
102
|
+
it 'leaves the message data intact' do
|
103
|
+
expect(message[:data]).to eql(hash_string_data)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'leaves the encoding intact' do
|
107
|
+
expect(message[:encoding]).to be_nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'message with nil payload' do
|
112
|
+
let(:message) { { data: nil, encoding: nil } }
|
113
|
+
|
114
|
+
it 'leaves the message data intact' do
|
115
|
+
expect(message[:data]).to be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'leaves the encoding intact' do
|
119
|
+
expect(message[:encoding]).to be_nil
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'message with no data payload' do
|
124
|
+
let(:message) { { encoding: nil } }
|
125
|
+
|
126
|
+
it 'leaves the message data intact' do
|
127
|
+
expect(message[:data]).to be_nil
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'leaves the encoding intact' do
|
131
|
+
expect(message[:encoding]).to be_nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|