ribbon-intercom 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dbc66058ef3f67f202ae929f759b20a1ca45a0f7
4
- data.tar.gz: d5eee408147e0cf447120c6f2ee8150cba30cec9
3
+ metadata.gz: c41ac1f0f1b5608ce40ce2610cc29cf28a8d7bc6
4
+ data.tar.gz: d975fe767bcc9bc0cc9bd3a6da43ba81b8054c88
5
5
  SHA512:
6
- metadata.gz: ed1f4b07d38b1fca0657cc08ec4fac171ae9fc65a7132f9afe4f46a9043d6104d4fec26ade902ab93bed155102365fdf56518dfbf93b0a2695805173b8d834b3
7
- data.tar.gz: 723e68476ea49afd0cf055e2ce6adcfb8636ea6c7d12625abfa9ff2486a1502bc4507af01a7fbfc5f4d8935ee1b0bc82de2a9e223547e99ec9513a6cd9e8fe81
6
+ metadata.gz: e5f12d2757fa4c8a1e1343df7b44ae31228d5a24572a6bfafba6356eacbb362f65d5530e778f68af3fafe9d99aef2fb4f672783b8b924d1ea29009a1bcb351a4
7
+ data.tar.gz: 44453cbf103d87a761d25b92934c501bc09c96b5a85d4cca97675303dd8c87cd65c7fd8c944a8de0fbdba45cc1b5cdde170aa8ca4c06c22dd7f508ff721ec1a1
@@ -84,7 +84,7 @@ module Ribbon::Intercom
84
84
  def _process_response(packet)
85
85
  _handle_response_error(packet) if packet.error?
86
86
 
87
- _init_packages(packet.retval)
87
+ Package.init_packages(packet.retval, self)
88
88
  packet
89
89
  end
90
90
 
@@ -94,20 +94,6 @@ module Ribbon::Intercom
94
94
  raise 'packet contains no error' unless packet.error?
95
95
  raise packet.error
96
96
  end
97
-
98
- ##
99
- # Walks the object and initializes all packages (i.e., sets them up to be
100
- # accessed by the end-user on the client).
101
- def _init_packages(object)
102
- Utils.walk(object) { |object|
103
- if object.is_a?(Package)
104
- object.sdk = dup
105
- object.mock_safe! if mock_safe?
106
- end
107
-
108
- object
109
- }
110
- end
111
97
  end # SDK
112
98
  end # Client
113
99
  end # Ribbon::Intercom
@@ -4,6 +4,49 @@ module Ribbon::Intercom
4
4
  class Package
5
5
  include Utils::Mixins::MockSafe
6
6
 
7
+ class << self
8
+ ##
9
+ # Package up any non-basic objects that include Packageable::Mixin.
10
+ def package(subject)
11
+ Utils.walk(subject) { |subject, context|
12
+ if Utils.basic_type?(subject)
13
+ subject
14
+ elsif context == :hash_key
15
+ # Hash keys must be basic types.
16
+ raise Errors::UnsafeResponseError, subject.inspect
17
+ elsif subject.is_a?(Packageable::Mixin)
18
+ _package_obj(subject, package(subject.package_data))
19
+ elsif subject.is_a?(Class) && subject < Packageable::Mixin
20
+ _package_obj(subject)
21
+ else
22
+ raise Errors::UnsafeResponseError, subject.inspect
23
+ end
24
+ }
25
+ end
26
+
27
+ def _package_obj(subject, data=nil)
28
+ new(encode_subject(subject), data)
29
+ end
30
+
31
+ def encode_subject(subject)
32
+ Marshal.dump(subject)
33
+ end
34
+
35
+ def decode_subject(encoded_subject)
36
+ Marshal.load(encoded_subject)
37
+ end
38
+
39
+ ##
40
+ # Walks the object and initializes all packages (i.e., sets them up to be
41
+ # accessed by the end-user on the client).
42
+ def init_packages(object, sdk)
43
+ Utils.walk(object) { |object|
44
+ object.send(:_init, sdk) if object.is_a?(Package)
45
+ object
46
+ }
47
+ end
48
+ end # Class Methods
49
+
7
50
  attr_reader :sdk
8
51
 
9
52
  def initialize(subject_data=nil, data=nil)
@@ -11,10 +54,11 @@ module Ribbon::Intercom
11
54
  @_data = data
12
55
  end
13
56
 
14
- def sdk=(sdk)
15
- @sdk = sdk
16
- end
17
-
57
+ ##
58
+ # Begin a method chain (must be completed with `#end`).
59
+ #
60
+ # When `#end` is called on the method chain, the chain will be resolved
61
+ # remotely. This allows the chain of methods to be executed in one round-trip.
18
62
  def begin
19
63
  Utils::MethodChain.begin { |methods|
20
64
  queue = Packet::MethodQueue.new
@@ -29,12 +73,26 @@ module Ribbon::Intercom
29
73
  if @_data && @_data.key?(meth)
30
74
  @_data[meth]
31
75
  elsif sdk
32
- _send_method_queue(Packet::MethodQueue.new.enqueue(meth, *args))
76
+ _call(meth, *args)
33
77
  else
34
78
  super
35
79
  end
36
80
  end
37
81
 
82
+ ##
83
+ # Call a method on the subject remotely.
84
+ def _call(method_name, *args)
85
+ _send_method_queue(Packet::MethodQueue.new.enqueue(method_name, *args))
86
+ end
87
+
88
+ ##
89
+ # Initializes the package on the client-side.
90
+ def _init(sdk)
91
+ @sdk = sdk
92
+ self.class.init_packages(@_data, sdk)
93
+ mock_safe! if sdk.mock_safe?
94
+ end
95
+
38
96
  def _send_method_queue(method_queue)
39
97
  _process_response(
40
98
  sdk.send_packet(
@@ -55,7 +113,7 @@ module Ribbon::Intercom
55
113
 
56
114
  def _process_response(packet)
57
115
  @_subject_data = packet.subject
58
- @_data = packet.package_data
116
+ @_data = self.class.init_packages(packet.package_data, sdk)
59
117
 
60
118
  packet.retval
61
119
  end
@@ -22,9 +22,7 @@ module Ribbon::Intercom
22
22
  ##
23
23
  # Returns the package data for the instance as a hash.
24
24
  def package_data
25
- Utils.sanitize(
26
- self.class._package_with_methods.map { |meth| [meth, public_send(meth)] }.to_h
27
- )
25
+ self.class._package_with_methods.map { |meth| [meth, public_send(meth)] }.to_h
28
26
  end
29
27
  end # Mixin
30
28
  end # Service::Subject
@@ -66,8 +66,19 @@ module Ribbon::Intercom
66
66
  store.lookup_channel(token)
67
67
  end
68
68
 
69
+ ##
70
+ # Check that the channel has sufficient permissions to call the method.
71
+ #
72
+ # The `send` method is forbidden because it breaks the encapsulation guaranteed
73
+ # by intercom (i.e., private methods can't be called).
74
+ #
75
+ # In addition to the permissions granted to the channel, all channels have
76
+ # implicit permission to call public methods on basic types.
69
77
  def sufficient_permissions?(base, intercom_method)
70
- Utils.basic_type?(base) || channel.may?(Utils.method_identifier(base, intercom_method))
78
+ intercom_method != :send && (
79
+ Utils.basic_type?(base) ||
80
+ channel.may?(Utils.method_identifier(base, intercom_method))
81
+ )
71
82
  end
72
83
 
73
84
  def call(env)
@@ -123,7 +134,7 @@ module Ribbon::Intercom
123
134
 
124
135
  def _load_subject
125
136
  if (encoded_subject=request_packet.subject) && !encoded_subject.empty?
126
- @subject = _decode_subject(encoded_subject)
137
+ @subject = Package.decode_subject(encoded_subject)
127
138
  _error!(Errors::InvalidSubjectSignatureError) unless @subject
128
139
  else
129
140
  @subject = self
@@ -150,7 +161,7 @@ module Ribbon::Intercom
150
161
  base = base.public_send(meth, *args)
151
162
  }
152
163
 
153
- _package(base)
164
+ Package.package(base)
154
165
  rescue NoMethodError => error
155
166
  if error.name == intercom_method
156
167
  _error!(Errors::InvalidMethodError, intercom_method)
@@ -173,11 +184,11 @@ module Ribbon::Intercom
173
184
  Packet.new.tap { |packet|
174
185
  unless self == subject # Order matters here! See: issue#52
175
186
  # Need to send subject back in case it was modified by the methods.
176
- packet.subject = _encode_subject(subject)
187
+ packet.subject = Package.encode_subject(subject)
177
188
 
178
189
  if subject.is_a?(Packageable::Mixin)
179
190
  # Need to send the package data back in case it changed, too.
180
- packet.package_data = subject.package_data
191
+ packet.package_data = Package.package(subject.package_data)
181
192
  end
182
193
  end
183
194
 
@@ -189,42 +200,6 @@ module Ribbon::Intercom
189
200
  _respond!(status, {}, packet.encode)
190
201
  end
191
202
 
192
- ##
193
- # Package up any non-basic objects that include Packageable::Mixin.
194
- def _package(object)
195
- Utils.walk(object) { |object, context|
196
- if Utils.basic_type?(object)
197
- object
198
- elsif context == :hash_key
199
- # Hash keys must be basic types.
200
- _error!(Errors::UnsafeResponseError, object.inspect)
201
- elsif object.is_a?(Packageable::Mixin)
202
- _package_obj(object, object.package_data)
203
- elsif object.is_a?(Class) && object < Packageable::Mixin
204
- _package_obj(object)
205
- else
206
- _error!(Errors::UnsafeResponseError, object.inspect)
207
- end
208
- }
209
- end
210
-
211
- def _package_obj(object, data=nil)
212
- Package.new(_encode_subject(object), data)
213
- end
214
-
215
- ##
216
- # Marshal dumps the subject and signs the resulting bytes with the channel.
217
- def _encode_subject(subject)
218
- channel.sign(Marshal.dump(subject))
219
- end
220
-
221
- ##
222
- # Decodes the subject sent from the client.
223
- def _decode_subject(encoded_subject)
224
- marshalled_subject = channel.verify(encoded_subject)
225
- marshalled_subject && Marshal.load(marshalled_subject)
226
- end
227
-
228
203
  def _request_authenticated?
229
204
  auth = Rack::Auth::Basic::Request.new(env)
230
205
 
@@ -1,5 +1,5 @@
1
1
  module Ribbon
2
2
  module Intercom
3
- VERSION = '0.4.0'
3
+ VERSION = '0.4.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ribbon-intercom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Honer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-05-21 00:00:00.000000000 Z
12
+ date: 2015-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack