bows 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ribbon/intercom.rb +42 -0
  3. data/lib/ribbon/intercom/client.rb +61 -0
  4. data/lib/ribbon/intercom/client/mock_sdk.rb +13 -0
  5. data/lib/ribbon/intercom/client/sdk.rb +99 -0
  6. data/lib/ribbon/intercom/client/sdk/adapters.rb +10 -0
  7. data/lib/ribbon/intercom/client/sdk/adapters/adapter.rb +77 -0
  8. data/lib/ribbon/intercom/client/sdk/adapters/adapter/response.rb +13 -0
  9. data/lib/ribbon/intercom/client/sdk/adapters/http_adapter.rb +32 -0
  10. data/lib/ribbon/intercom/client/sdk/adapters/http_adapter/connection.rb +34 -0
  11. data/lib/ribbon/intercom/client/sdk/adapters/local_adapter.rb +55 -0
  12. data/lib/ribbon/intercom/client/sdk/adapters/mock_adapter.rb +40 -0
  13. data/lib/ribbon/intercom/errors.rb +66 -0
  14. data/lib/ribbon/intercom/package.rb +121 -0
  15. data/lib/ribbon/intercom/packageable.rb +6 -0
  16. data/lib/ribbon/intercom/packageable/mixin.rb +29 -0
  17. data/lib/ribbon/intercom/packet.rb +52 -0
  18. data/lib/ribbon/intercom/packet/method_queue.rb +28 -0
  19. data/lib/ribbon/intercom/railtie.rb +14 -0
  20. data/lib/ribbon/intercom/service.rb +273 -0
  21. data/lib/ribbon/intercom/service/channel.rb +203 -0
  22. data/lib/ribbon/intercom/service/channel/stores.rb +9 -0
  23. data/lib/ribbon/intercom/service/channel/stores/mock_store.rb +40 -0
  24. data/lib/ribbon/intercom/service/channel/stores/redis_store.rb +196 -0
  25. data/lib/ribbon/intercom/service/channel/stores/store.rb +31 -0
  26. data/lib/ribbon/intercom/utils.rb +72 -0
  27. data/lib/ribbon/intercom/utils/method_chain.rb +38 -0
  28. data/lib/ribbon/intercom/utils/mixins.rb +5 -0
  29. data/lib/ribbon/intercom/utils/mixins/mock_safe.rb +26 -0
  30. data/lib/ribbon/intercom/utils/signer.rb +71 -0
  31. data/lib/ribbon/intercom/version.rb +5 -0
  32. data/lib/tasks/intercom.rake +24 -0
  33. metadata +215 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1f136b3b94c864c9bdfff6829ee3add739e565ec
4
+ data.tar.gz: 34d7ab35c8d8e417f040faa34d1bf16dcb3f553e
5
+ SHA512:
6
+ metadata.gz: 759458f070d855822f8597379c8ad392935d1548d039bd85ac281719ac5114054ef18fab3beeed7625fb93c1704ee26ce511796b8f5eac8e8b589e59feb720b8
7
+ data.tar.gz: 926eb6957418a8564100da028b20b66b132636103dc8f963b74de747a6c0793964c500fad994fc3ae0e6af635ae3ef50b072a2b1529687e94c27ace520920b50
@@ -0,0 +1,42 @@
1
+ require 'ribbon/intercom/version'
2
+ require 'rack'
3
+
4
+ module Ribbon
5
+ module Intercom
6
+ require 'ribbon/intercom/railtie' if defined?(Rails)
7
+ autoload(:Service, 'ribbon/intercom/service')
8
+ autoload(:Errors, 'ribbon/intercom/errors')
9
+ autoload(:Client, 'ribbon/intercom/client')
10
+ autoload(:Package, 'ribbon/intercom/package')
11
+ autoload(:Packageable, 'ribbon/intercom/packageable')
12
+ autoload(:Packet, 'ribbon/intercom/packet')
13
+ autoload(:Utils, 'ribbon/intercom/utils')
14
+
15
+ module_function
16
+
17
+ def load_tasks
18
+ Dir[
19
+ File.expand_path("../../tasks", __FILE__) + '/**.rake'
20
+ ].each { |rake_file| load rake_file }
21
+ end
22
+
23
+ def method_missing(meth, *args, &block)
24
+ client.send(meth, *args, &block)
25
+ end
26
+
27
+ def client
28
+ @_client ||= Client.new
29
+ end
30
+
31
+ def mock_safe
32
+ orig_client = client
33
+ @_client = @_client.mock_safe
34
+ yield
35
+ ensure
36
+ @_client = orig_client
37
+ end
38
+ end # Intercom
39
+ end # Ribbon
40
+
41
+ # Create a shortcut to the module
42
+ Intercom = Ribbon::Intercom
@@ -0,0 +1,61 @@
1
+ require 'ribbon/config'
2
+
3
+ module Ribbon::Intercom
4
+ class Client
5
+ autoload(:SDK, 'ribbon/intercom/client/sdk')
6
+ autoload(:MockSDK, 'ribbon/intercom/client/mock_sdk')
7
+
8
+ def config(&block)
9
+ (@__config ||= Ribbon::Config.new).tap { |config|
10
+ if block_given?
11
+ config.define(&block)
12
+ end
13
+ }
14
+ end
15
+
16
+ def [](handle)
17
+ _load_sdk(handle)
18
+ end
19
+
20
+ ##
21
+ # Return a mock safe version of this client.
22
+ def mock_safe
23
+ dup.tap { |client|
24
+ client.preload_sdks
25
+
26
+ # Make SDK instances mock safe
27
+ client.sdk_instances = Hash[
28
+ client.sdk_instances.map { |service, sdk| [service, sdk.mock_safe] }
29
+ ]
30
+ }
31
+ end
32
+
33
+ def preload_sdks
34
+ if config.service?
35
+ config.service.each { |name, *args|
36
+ _load_sdk(name)
37
+ }
38
+ end
39
+ end
40
+
41
+ protected
42
+
43
+ attr_accessor :sdk_instances
44
+
45
+ private
46
+
47
+ def _load_sdk(handle)
48
+ raise Errors::ServiceNotDefinedError unless config.service?
49
+
50
+ (self.sdk_instances ||= Hash.new { |hash, key|
51
+ # Get the last service if there are duplicates
52
+ if (service_def = config.service.select { |r| r.first == key }.last)
53
+ name, config = service_def
54
+ hash[key] = SDK.new(config[:url], config[:token], config[:secret])
55
+ else
56
+ raise Errors::ServiceNotDefinedError
57
+ end
58
+ })[handle.to_sym]
59
+ end
60
+ end # Client
61
+ end # Ribbon::Intercom
@@ -0,0 +1,13 @@
1
+ module Ribbon::Intercom
2
+ class Client
3
+ class MockSDK < SDK
4
+ def initialize(service)
5
+ super(Adapters::MockAdapter.new(service))
6
+ end
7
+
8
+ def with_permissions(*perms, &block)
9
+ adapter.with_permissions(*perms, &block)
10
+ end
11
+ end # MockSDK
12
+ end # Client
13
+ end # Ribbon::Intercom
@@ -0,0 +1,99 @@
1
+ require 'base64'
2
+
3
+ module Ribbon::Intercom
4
+ class Client
5
+ class SDK
6
+ autoload(:Adapters, 'ribbon/intercom/client/sdk/adapters')
7
+
8
+ include Utils::Mixins::MockSafe
9
+
10
+ attr_reader :adapter
11
+
12
+ def initialize(*args)
13
+ case args.first
14
+ when Adapters::Adapter
15
+ self.adapter = args.first
16
+ else
17
+ self.adapter = Adapters::HttpAdapter.new(*args)
18
+ end
19
+ end
20
+
21
+ def begin
22
+ Utils::MethodChain.begin { |methods|
23
+ queue = Packet::MethodQueue.new
24
+ methods.each { |meth, *args| queue.enqueue(meth, *args) }
25
+ send_packet(method_queue: queue).retval
26
+ }
27
+ end
28
+
29
+ ##
30
+ # Returns the headers defined for this SDK. Optionally, you may also define
31
+ # additional headers you'd like to add/override.
32
+ def headers(new_headers={})
33
+ adapter.headers(new_headers)
34
+ end
35
+
36
+ def connect(*args)
37
+ adapter.connect(*args)
38
+ end
39
+
40
+ def connected?
41
+ adapter.connected?
42
+ end
43
+
44
+ ##
45
+ # Calls the method on the adapter returning the response Packet
46
+ def call(method_name, *args)
47
+ send_packet(
48
+ method_queue: Packet::MethodQueue.new.enqueue(method_name, *args)
49
+ )
50
+ end
51
+
52
+ ##
53
+ # Sends the packet with the adapter, returning the response Packet.
54
+ #
55
+ # Intended to be called by Package.
56
+ def send_packet(packet)
57
+ _process_response(adapter.send_packet(packet))
58
+ end
59
+
60
+ def dup
61
+ super.tap { |sdk|
62
+ sdk.adapter = adapter.dup
63
+ }
64
+ end
65
+
66
+ protected
67
+
68
+ def adapter=(adapter)
69
+ @adapter = adapter
70
+ end
71
+
72
+ private
73
+
74
+ ##
75
+ # Simulates calling the remote method as if it were a local method.
76
+ #
77
+ # Intended to be called by end-users.
78
+ def method_missing(meth, *args, &block)
79
+ call(meth, *args).retval
80
+ end
81
+
82
+ ##
83
+ # Process a Packet object returned by Adapter#send_packet.
84
+ def _process_response(packet)
85
+ _handle_response_error(packet) if packet.error?
86
+
87
+ Package.init_packages(packet.retval, self)
88
+ packet
89
+ end
90
+
91
+ ##
92
+ # Raises an error depending on what went wrong.
93
+ def _handle_response_error(packet)
94
+ raise 'packet contains no error' unless packet.error?
95
+ raise packet.error
96
+ end
97
+ end # SDK
98
+ end # Client
99
+ end # Ribbon::Intercom
@@ -0,0 +1,10 @@
1
+ module Ribbon::Intercom
2
+ class Client::SDK
3
+ module Adapters
4
+ autoload(:Adapter, 'ribbon/intercom/client/sdk/adapters/adapter')
5
+ autoload(:HttpAdapter, 'ribbon/intercom/client/sdk/adapters/http_adapter')
6
+ autoload(:LocalAdapter, 'ribbon/intercom/client/sdk/adapters/local_adapter')
7
+ autoload(:MockAdapter, 'ribbon/intercom/client/sdk/adapters/mock_adapter')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,77 @@
1
+ module Ribbon::Intercom
2
+ module Client::SDK::Adapters
3
+ class Adapter
4
+ autoload(:Response, 'ribbon/intercom/client/sdk/adapters/adapter/response')
5
+
6
+ def initialize(*args)
7
+ connect(*args)
8
+ end
9
+
10
+ ##
11
+ # Call the method on the service.
12
+ #
13
+ # @deprecated This method is only called by tests. Don't call it elsewhere.
14
+ def call(method_name, *args)
15
+ send_packet(
16
+ method_queue: Packet::MethodQueue.new.enqueue(method_name, *args)
17
+ )
18
+ end
19
+
20
+ ##
21
+ # Send a packet to the service and returns the Packet returned by the service.
22
+ def send_packet(packet)
23
+ packet = Packet.new(packet) if packet.is_a?(Hash)
24
+
25
+ send_packet!(packet.encode).tap { |response|
26
+ raise TypeError, "send_packet! should return an Adapter::Response" unless response.is_a?(Response)
27
+ }.packet
28
+ end
29
+
30
+ ##
31
+ # Returns the headers defined for this Adapter. Optionally, you may also
32
+ # define additional headers you'd like to add/override.
33
+ def headers(new_headers={})
34
+ (@headers ||= {}).merge!(new_headers)
35
+ end
36
+
37
+ def dup
38
+ super.tap { |adapter|
39
+ adapter.headers = @headers.dup if @headers
40
+ }
41
+ end
42
+
43
+ ##
44
+ # Connect to a service. The specific arguments depend on the Adapter
45
+ # subclass.
46
+ def connect(*args)
47
+ raise NotImplementedError
48
+ end
49
+
50
+ ##
51
+ # Returns whether or not the Adapter is connected to a service.
52
+ def connected?
53
+ raise NotImplementedError
54
+ end
55
+
56
+ ##
57
+ # Actually send the packet to the service. Should return an Adapter::Response object.
58
+ def send_packet!(packet)
59
+ raise NotImplementedError
60
+ end
61
+
62
+ protected
63
+
64
+ def headers=(h)
65
+ @headers = h
66
+ end
67
+
68
+ private
69
+
70
+ ##
71
+ # Encode the arguments for transmission to the service.
72
+ def _encode_args(*args)
73
+ Base64.strict_encode64(Marshal.dump(Utils.sanitize(args)))
74
+ end
75
+ end # Adapter
76
+ end # Client::SDK::Adapters
77
+ end # Ribbon::Intercom
@@ -0,0 +1,13 @@
1
+ module Ribbon::Intercom
2
+ class Client::SDK::Adapters::Adapter
3
+ class Response < Rack::Response
4
+ def body
5
+ super.join
6
+ end
7
+
8
+ def packet
9
+ @__packet ||= Packet.decode(body) unless body.empty?
10
+ end
11
+ end # Response
12
+ end # Client::SDK::Adapters::Adapter
13
+ end # Ribbon::Intercom
@@ -0,0 +1,32 @@
1
+ module Ribbon::Intercom
2
+ module Client::SDK::Adapters
3
+ class HttpAdapter < Adapter
4
+ autoload(:Connection, 'ribbon/intercom/client/sdk/adapters/http_adapter/connection')
5
+
6
+ attr_reader :connection
7
+
8
+ def connect(*args)
9
+ @_connection_args = args.dup
10
+ end
11
+
12
+ def connected?
13
+ !!connection
14
+ end
15
+
16
+ def connection
17
+ @__connection ||= Connection.new(*@_connection_args)
18
+ end
19
+
20
+ ##
21
+ # Send the encoded packet up to the service via an HTTP PUT.
22
+ def send_packet!(encoded_packet)
23
+ response = connection.put(
24
+ headers: headers,
25
+ body: encoded_packet
26
+ )
27
+
28
+ Adapter::Response.new(response.body, response.code.to_i, response)
29
+ end
30
+ end # HttpAdapter
31
+ end # Client::SDK::Adapters
32
+ end # Ribbon::Intercom
@@ -0,0 +1,34 @@
1
+ require 'net/http'
2
+ require 'openssl'
3
+ require 'uri'
4
+
5
+ module Ribbon::Intercom
6
+ module Client::SDK::Adapters
7
+ class HttpAdapter::Connection
8
+ attr_reader :url
9
+
10
+ def initialize(url, token, secret)
11
+ @url = url.is_a?(String) ? URI(url) : url
12
+
13
+ @_client = Net::HTTP.new(@url.hostname, @url.port)
14
+ @_client.use_ssl = @url.is_a?(URI::HTTPS)
15
+ @_client.verify_mode = OpenSSL::SSL::VERIFY_PEER
16
+ @_client.cert_store = OpenSSL::X509::Store.new.tap { |s| s.set_default_paths }
17
+
18
+ @_headers = {
19
+ 'Authorization' => "Basic #{Base64.strict_encode64("#{token}:#{secret}")}"
20
+ }
21
+ end
22
+
23
+ def put(params={})
24
+ @_client.put(url.request_uri, params[:body], _prepare_headers(params[:headers]).merge(@_headers))
25
+ end
26
+
27
+ private
28
+
29
+ def _prepare_headers(headers)
30
+ Hash[(headers || {}).map { |k, v| [k.to_s, v.to_s] }]
31
+ end
32
+ end # HttpAdapter::Connection
33
+ end # Client::SDK::Adapters
34
+ end # Ribbon::Intercom
@@ -0,0 +1,55 @@
1
+ require 'base64'
2
+
3
+ module Ribbon::Intercom
4
+ module Client::SDK::Adapters
5
+ class LocalAdapter < Adapter
6
+ attr_reader :service
7
+ attr_accessor :channel_token
8
+ attr_accessor :channel_secret
9
+
10
+ def connect(service, params={})
11
+ case service
12
+ when Service
13
+ @service = service
14
+ else
15
+ raise ArgumentError, "Expected a service, got: #{service.inspect}"
16
+ end
17
+
18
+ @channel_token = params[:channel_token]
19
+ @channel_secret = params[:channel_secret]
20
+ end
21
+
22
+ def connected?(*args)
23
+ !!service
24
+ end
25
+
26
+ ##
27
+ # Mimics an HTTP PUT
28
+ def send_packet!(encoded_packet)
29
+ response = service.call(
30
+ _http_headers.merge(
31
+ 'HTTP_AUTHORIZATION' => _http_auth,
32
+ 'REQUEST_METHOD' => 'PUT',
33
+ 'rack.input' => StringIO.new(encoded_packet)
34
+ )
35
+ )
36
+
37
+ Adapter::Response.new(response[2], response[0], response[1])
38
+ end
39
+
40
+ private
41
+
42
+ def _http_auth
43
+ "Basic #{Base64.strict_encode64("#{channel_token}:#{channel_secret}")}"
44
+ end
45
+
46
+ def _http_headers
47
+ Hash[headers.map { |name, value| [_header_to_http(name), value] }]
48
+ end
49
+
50
+ def _header_to_http(name)
51
+ "HTTP_#{name.to_s.upcase.gsub('-', '_')}"
52
+ end
53
+ end # MockAdapter
54
+ end # Client::SDK::Adapters
55
+ end # Ribbon::Intercom