bows 0.0.1
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 +7 -0
- data/lib/ribbon/intercom.rb +42 -0
- data/lib/ribbon/intercom/client.rb +61 -0
- data/lib/ribbon/intercom/client/mock_sdk.rb +13 -0
- data/lib/ribbon/intercom/client/sdk.rb +99 -0
- data/lib/ribbon/intercom/client/sdk/adapters.rb +10 -0
- data/lib/ribbon/intercom/client/sdk/adapters/adapter.rb +77 -0
- data/lib/ribbon/intercom/client/sdk/adapters/adapter/response.rb +13 -0
- data/lib/ribbon/intercom/client/sdk/adapters/http_adapter.rb +32 -0
- data/lib/ribbon/intercom/client/sdk/adapters/http_adapter/connection.rb +34 -0
- data/lib/ribbon/intercom/client/sdk/adapters/local_adapter.rb +55 -0
- data/lib/ribbon/intercom/client/sdk/adapters/mock_adapter.rb +40 -0
- data/lib/ribbon/intercom/errors.rb +66 -0
- data/lib/ribbon/intercom/package.rb +121 -0
- data/lib/ribbon/intercom/packageable.rb +6 -0
- data/lib/ribbon/intercom/packageable/mixin.rb +29 -0
- data/lib/ribbon/intercom/packet.rb +52 -0
- data/lib/ribbon/intercom/packet/method_queue.rb +28 -0
- data/lib/ribbon/intercom/railtie.rb +14 -0
- data/lib/ribbon/intercom/service.rb +273 -0
- data/lib/ribbon/intercom/service/channel.rb +203 -0
- data/lib/ribbon/intercom/service/channel/stores.rb +9 -0
- data/lib/ribbon/intercom/service/channel/stores/mock_store.rb +40 -0
- data/lib/ribbon/intercom/service/channel/stores/redis_store.rb +196 -0
- data/lib/ribbon/intercom/service/channel/stores/store.rb +31 -0
- data/lib/ribbon/intercom/utils.rb +72 -0
- data/lib/ribbon/intercom/utils/method_chain.rb +38 -0
- data/lib/ribbon/intercom/utils/mixins.rb +5 -0
- data/lib/ribbon/intercom/utils/mixins/mock_safe.rb +26 -0
- data/lib/ribbon/intercom/utils/signer.rb +71 -0
- data/lib/ribbon/intercom/version.rb +5 -0
- data/lib/tasks/intercom.rake +24 -0
- metadata +215 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module Ribbon::Intercom
|
2
|
+
class Service
|
3
|
+
module Channel::Stores
|
4
|
+
class Store
|
5
|
+
def open_channel(params={})
|
6
|
+
Channel.new(self, params)
|
7
|
+
end
|
8
|
+
|
9
|
+
def token_exists?(token)
|
10
|
+
raise NotImplementedError
|
11
|
+
end
|
12
|
+
|
13
|
+
def lookup_channel(token)
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
def persist(channel)
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete(channel)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
def with_lock(channel, &block)
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
end # Store
|
29
|
+
end # Channel::Stores
|
30
|
+
end # Service
|
31
|
+
end # Ribbon::Intercom
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Ribbon::Intercom
|
4
|
+
module Utils
|
5
|
+
autoload(:Signer, 'ribbon/intercom/utils/signer')
|
6
|
+
autoload(:MethodChain, 'ribbon/intercom/utils/method_chain')
|
7
|
+
autoload(:Mixins, 'ribbon/intercom/utils/mixins')
|
8
|
+
|
9
|
+
BASIC_TYPES = [
|
10
|
+
String, Symbol, TrueClass, FalseClass, Integer, Float, NilClass,
|
11
|
+
Date, Time, DateTime,
|
12
|
+
Hash, Array, Range
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def basic_type?(object)
|
17
|
+
case object
|
18
|
+
when *BASIC_TYPES then true
|
19
|
+
else false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def walk(object, context=nil, &block)
|
24
|
+
case object
|
25
|
+
when Hash
|
26
|
+
Hash[
|
27
|
+
object.map { |key, val|
|
28
|
+
[walk(key, :hash_key, &block), walk(val, :hash_value, &block)]
|
29
|
+
}
|
30
|
+
]
|
31
|
+
when Array
|
32
|
+
object.map { |obj| walk(obj, :array_elem, &block) }
|
33
|
+
when Range
|
34
|
+
Range.new(
|
35
|
+
walk(object.begin, :range_begin, &block),
|
36
|
+
walk(object.end, :range_end, &block),
|
37
|
+
object.exclude_end?
|
38
|
+
)
|
39
|
+
else
|
40
|
+
yield object, context
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Raises an error if the object is or contains any non-basic types.
|
46
|
+
def sanitize(object)
|
47
|
+
walk(object) { |object|
|
48
|
+
if basic_type?(object)
|
49
|
+
object
|
50
|
+
else
|
51
|
+
raise Errors::UnsafeValueError, object.inspect
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def symbolize_keys(hash)
|
57
|
+
hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
58
|
+
end
|
59
|
+
|
60
|
+
def classify(str)
|
61
|
+
str.split("_").map(&:capitalize).join
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Returns an identifier for the method (e.g., A::B::C#method_name)
|
66
|
+
def method_identifier(subject, method)
|
67
|
+
scope = subject.is_a?(Class) ? subject.name : subject.class.name
|
68
|
+
scope + (subject.is_a?(Class) ? '.' : '#') + method.to_s
|
69
|
+
end
|
70
|
+
end # Class methods
|
71
|
+
end # Utils
|
72
|
+
end # Ribbon::Intercom
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Ribbon::Intercom
|
2
|
+
module Utils
|
3
|
+
class MethodChain
|
4
|
+
class << self
|
5
|
+
def begin(&block)
|
6
|
+
new(&block)
|
7
|
+
end
|
8
|
+
end # Class Methods
|
9
|
+
|
10
|
+
##
|
11
|
+
# Need to override all public instance methods so they can be captured correctly.
|
12
|
+
public_instance_methods.each { |meth|
|
13
|
+
define_method(meth) { |*args|
|
14
|
+
_add_method(meth, *args)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
def initialize(&block)
|
19
|
+
@_end_block = block
|
20
|
+
end
|
21
|
+
|
22
|
+
def end
|
23
|
+
@_end_block.call(@_methods)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def method_missing(meth, *args, &block)
|
29
|
+
_add_method(meth, *args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def _add_method(meth, *args)
|
33
|
+
(@_methods ||= []) << [meth, *args]
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end # MethodChain
|
37
|
+
end # Utils
|
38
|
+
end # Ribbon::Intercom
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ribbon::Intercom
|
2
|
+
module Utils::Mixins
|
3
|
+
module MockSafe
|
4
|
+
##
|
5
|
+
# Return a mock safe version of this package.
|
6
|
+
def mock_safe
|
7
|
+
dup.tap { |obj| obj.mock_safe! }
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Make this package mock safe.
|
12
|
+
def mock_safe!
|
13
|
+
unless mock_safe?
|
14
|
+
@_mock_safe = true
|
15
|
+
|
16
|
+
# For RSpec: Allow any method to be mocked on this instance.
|
17
|
+
define_singleton_method(:respond_to?) { |*args| true }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def mock_safe?
|
22
|
+
!!@_mock_safe
|
23
|
+
end
|
24
|
+
end # MockSafe
|
25
|
+
end # Utils::Mixin
|
26
|
+
end # Ribbon::Intercom
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module Ribbon::Intercom
|
5
|
+
module Utils
|
6
|
+
class Signer
|
7
|
+
class << self
|
8
|
+
def random_key
|
9
|
+
SecureRandom.random_bytes(32)
|
10
|
+
end
|
11
|
+
|
12
|
+
def random_salt
|
13
|
+
SecureRandom.random_bytes(8)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :key
|
18
|
+
|
19
|
+
def initialize(key=self.class.random_key)
|
20
|
+
raise ArgumentError, "key must be defined" unless key
|
21
|
+
@key = key.dup.freeze
|
22
|
+
@_digest = OpenSSL::Digest::SHA256.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def sign(data)
|
26
|
+
unless data.is_a?(String) && data.encoding == Encoding::BINARY
|
27
|
+
raise ArgumentError, "data must be a binary encoded string"
|
28
|
+
end
|
29
|
+
|
30
|
+
salt = self.class.random_salt
|
31
|
+
signature = _sign(salt, data)
|
32
|
+
_encode(signature, salt, data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify(signed_data)
|
36
|
+
unless signed_data.is_a?(String) && signed_data.encoding == Encoding::BINARY
|
37
|
+
raise ArgumentError, "signed_data must be a binary encoded string"
|
38
|
+
end
|
39
|
+
|
40
|
+
signature, salt, data = _decode(signed_data)
|
41
|
+
data if _sign(salt, data) == signature
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def _sign(salt, data)
|
47
|
+
OpenSSL::HMAC.digest(@_digest, key, salt + data)
|
48
|
+
end
|
49
|
+
|
50
|
+
def _encode(signature, salt, data)
|
51
|
+
"\x01" + signature + salt + data
|
52
|
+
end
|
53
|
+
|
54
|
+
def _decode(signed_data)
|
55
|
+
index = 0
|
56
|
+
version = signed_data[index]
|
57
|
+
|
58
|
+
index += version.length
|
59
|
+
signature = signed_data.slice(index, @_digest.length)
|
60
|
+
|
61
|
+
index += signature.length
|
62
|
+
salt = signed_data.slice(index, 8)
|
63
|
+
|
64
|
+
index += salt.length
|
65
|
+
data = signed_data.slice(index..-1)
|
66
|
+
|
67
|
+
[signature, salt, data]
|
68
|
+
end
|
69
|
+
end # Signer
|
70
|
+
end # Utils
|
71
|
+
end # Ribbon::Intercom
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ribbon/intercom'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
namespace :intercom do
|
6
|
+
namespace :client do
|
7
|
+
task :rotate_secret, [:service] => :environment do |t, args|
|
8
|
+
service = args[:service]
|
9
|
+
puts "New #{service} secret: #{Intercom[service].rotate_secret}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :service do
|
14
|
+
task :open_channel, [:service_name, :channel_name, :permissions] => :environment do |t, args|
|
15
|
+
service = Intercom::Utils.classify(args[:service_name])
|
16
|
+
channel_name = args[:channel_name]
|
17
|
+
permissions = args[:permissions].split(" ")
|
18
|
+
|
19
|
+
channel = Intercom::const_get(service).open_channel(name: channel_name, may: permissions)
|
20
|
+
secret = channel.rotate_secret!
|
21
|
+
puts "New channel: #{channel_name} with token: #{channel.token} and secret: #{secret} with permissions: #{channel.permissions.to_a.inspect}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bows
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Honer
|
8
|
+
- Kayvon Ghaffari
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-06-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.5'
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.5.2
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '1.5'
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.5.2
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: bcrypt
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.1.3
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 3.1.3
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 3.1.3
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 3.1.3
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: redis
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: ribbon-config
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.1.0
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.1.0
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rspec
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: rspec-rails
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: sqlite3
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
type: :development
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: rails
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 4.0.0
|
131
|
+
type: :development
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 4.0.0
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
name: mock_redis
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
type: :development
|
146
|
+
prerelease: false
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
description: A standard for authenticating requests among services
|
153
|
+
email:
|
154
|
+
- robert@ribbonpayments.com
|
155
|
+
- kayvon@ribbon.co
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- lib/ribbon/intercom.rb
|
161
|
+
- lib/ribbon/intercom/client.rb
|
162
|
+
- lib/ribbon/intercom/client/mock_sdk.rb
|
163
|
+
- lib/ribbon/intercom/client/sdk.rb
|
164
|
+
- lib/ribbon/intercom/client/sdk/adapters.rb
|
165
|
+
- lib/ribbon/intercom/client/sdk/adapters/adapter.rb
|
166
|
+
- lib/ribbon/intercom/client/sdk/adapters/adapter/response.rb
|
167
|
+
- lib/ribbon/intercom/client/sdk/adapters/http_adapter.rb
|
168
|
+
- lib/ribbon/intercom/client/sdk/adapters/http_adapter/connection.rb
|
169
|
+
- lib/ribbon/intercom/client/sdk/adapters/local_adapter.rb
|
170
|
+
- lib/ribbon/intercom/client/sdk/adapters/mock_adapter.rb
|
171
|
+
- lib/ribbon/intercom/errors.rb
|
172
|
+
- lib/ribbon/intercom/package.rb
|
173
|
+
- lib/ribbon/intercom/packageable.rb
|
174
|
+
- lib/ribbon/intercom/packageable/mixin.rb
|
175
|
+
- lib/ribbon/intercom/packet.rb
|
176
|
+
- lib/ribbon/intercom/packet/method_queue.rb
|
177
|
+
- lib/ribbon/intercom/railtie.rb
|
178
|
+
- lib/ribbon/intercom/service.rb
|
179
|
+
- lib/ribbon/intercom/service/channel.rb
|
180
|
+
- lib/ribbon/intercom/service/channel/stores.rb
|
181
|
+
- lib/ribbon/intercom/service/channel/stores/mock_store.rb
|
182
|
+
- lib/ribbon/intercom/service/channel/stores/redis_store.rb
|
183
|
+
- lib/ribbon/intercom/service/channel/stores/store.rb
|
184
|
+
- lib/ribbon/intercom/utils.rb
|
185
|
+
- lib/ribbon/intercom/utils/method_chain.rb
|
186
|
+
- lib/ribbon/intercom/utils/mixins.rb
|
187
|
+
- lib/ribbon/intercom/utils/mixins/mock_safe.rb
|
188
|
+
- lib/ribbon/intercom/utils/signer.rb
|
189
|
+
- lib/ribbon/intercom/version.rb
|
190
|
+
- lib/tasks/intercom.rake
|
191
|
+
homepage: http://github.com/ribbon/intercom
|
192
|
+
licenses:
|
193
|
+
- BSD
|
194
|
+
metadata: {}
|
195
|
+
post_install_message:
|
196
|
+
rdoc_options: []
|
197
|
+
require_paths:
|
198
|
+
- lib
|
199
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
requirements: []
|
210
|
+
rubyforge_project:
|
211
|
+
rubygems_version: 2.4.3
|
212
|
+
signing_key:
|
213
|
+
specification_version: 4
|
214
|
+
summary: A standard for authenticating requests among services
|
215
|
+
test_files: []
|