ephemeral_calc 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ephemeral_calc.gemspec +2 -0
- data/exe/ephemeral_calc +23 -27
- data/lib/ephemeral_calc/registration.rb +89 -0
- data/lib/ephemeral_calc/version.rb +1 -1
- data/lib/ephemeral_calc.rb +3 -4
- metadata +17 -6
- data/lib/ephemeral_calc/google_api/client.rb +0 -82
- data/lib/ephemeral_calc/google_api/credentials.rb +0 -39
- data/lib/ephemeral_calc/google_api/oauth.rb +0 -87
- data/lib/ephemeral_calc/google_api/request.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d66ed2f2feb08b61474d5e99d9906de5702b409a
|
4
|
+
data.tar.gz: 448f9eb5dbad2eb1cc99e097f384d0041a60ebcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f4e472ea04511a2406a17897c2571a4337dbffef92796661d8b66de8e5a26ce4a834859b0e6352cda6e26d147535cd27cf8ab55c994e533822e9b7979eb8914
|
7
|
+
data.tar.gz: f0a98210f4e975c70ef30de5beb8c2dc6af80b2837eb9d6969f7d5afec7e938883467b38c6907d3daa7ec44733d4057d4d6d8ab049e255b6ca1c2da05bceb686
|
data/ephemeral_calc.gemspec
CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.extensions = %w[ext/curve25519/extconf.rb]
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
+
spec.add_runtime_dependency "proximity_beacon", "~> 0.1.3"
|
24
|
+
|
23
25
|
spec.add_development_dependency "bundler", "~> 1.10"
|
24
26
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
27
|
spec.add_development_dependency "rspec"
|
data/exe/ephemeral_calc
CHANGED
@@ -53,11 +53,13 @@ Commands:
|
|
53
53
|
access the API.
|
54
54
|
|
55
55
|
register:
|
56
|
-
ephemeral_calc register <
|
56
|
+
ephemeral_calc register <beacon_description> [<rotation_exp> [<namespace> [<instance]]]
|
57
57
|
|
58
|
-
Registers an EID beacon with Google's Proximity Beacon API. All
|
59
|
-
|
60
|
-
|
58
|
+
Registers an EID beacon with Google's Proximity Beacon API. All byte strings should be in hex. If you
|
59
|
+
do not supply a namespace it will use the following: 'e3dd811dd3bbe49e630a'. If you do not supply an
|
60
|
+
instance it will randomly generate one. Uses environment variables "GOOGLE_CLIENT_ID" and
|
61
|
+
"GOOGLE_CLIENT_SECRET" to do the neccessary OAuth in order to access the API. Outputs YAML which
|
62
|
+
contains all the information necessary to advertise as this registered beacon.
|
61
63
|
|
62
64
|
keygen:
|
63
65
|
ephemeral_calc keygen
|
@@ -135,18 +137,17 @@ eos
|
|
135
137
|
eid_hex = ARGV.shift
|
136
138
|
api_key = ENV["GOOGLE_API_KEY"]
|
137
139
|
|
140
|
+
client = ProximityBeacon::Client.new
|
138
141
|
if api_key
|
139
|
-
client = EphemeralCalc::GoogleAPI::Client.new(nil) # don't try oauth
|
140
142
|
response = client.getforobserved(eid_hex, api_key)
|
141
143
|
beacons = response["beacons"]
|
142
144
|
beacon = beacons[0] if beacons
|
143
145
|
else
|
144
146
|
beacon_name = "beacons/4!#{eid_hex.downcase}"
|
145
147
|
begin
|
146
|
-
beacon =
|
147
|
-
attachments =
|
148
|
-
|
149
|
-
rescue EphemeralCalc::GoogleAPI::RequestError => e
|
148
|
+
beacon = client.beacons.get(beacon_name).as_json
|
149
|
+
beacon["attachments"] = client.attachments.list(beacon_name).map(&:as_json)
|
150
|
+
rescue ProximityBeacon::Client::RequestError => e
|
150
151
|
# if we get a 404, the EID doesn't resolve
|
151
152
|
raise e unless e.code == 404
|
152
153
|
end
|
@@ -161,7 +162,7 @@ eos
|
|
161
162
|
|
162
163
|
def eidparams
|
163
164
|
require 'yaml'
|
164
|
-
eidparams =
|
165
|
+
eidparams = ProximityBeacon::Client.new.eidparams
|
165
166
|
key_hex = to_hex(Base64.decode64(eidparams["serviceEcdhPublicKey"]))
|
166
167
|
eidparams["serviceEcdhPublicKeyHex"] = key_hex
|
167
168
|
puts eidparams.to_yaml
|
@@ -177,15 +178,18 @@ eos
|
|
177
178
|
|
178
179
|
def register
|
179
180
|
require 'yaml'
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
181
|
+
name = ARGV.shift
|
182
|
+
rotation_exp = ARGV.shift
|
183
|
+
namespace = ARGV.shift
|
184
|
+
instance = ARGV.shift
|
185
|
+
registration = EphemeralCalc::Registration.new(
|
186
|
+
name: name,
|
187
|
+
rotation_exp: rotation_exp,
|
188
|
+
namespace: namespace,
|
189
|
+
instance: instance
|
190
|
+
)
|
191
|
+
registration.register
|
192
|
+
puts registration.to_yaml
|
189
193
|
end
|
190
194
|
|
191
195
|
def keygen
|
@@ -207,14 +211,6 @@ eos
|
|
207
211
|
end
|
208
212
|
end
|
209
213
|
|
210
|
-
def oauth_client
|
211
|
-
@oauth_client ||=
|
212
|
-
begin
|
213
|
-
client = EphemeralCalc::GoogleAPI::Client.new
|
214
|
-
client.credentials.save
|
215
|
-
client
|
216
|
-
end
|
217
|
-
end
|
218
214
|
end
|
219
215
|
|
220
216
|
app = App.new
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module EphemeralCalc
|
2
|
+
class Registration
|
3
|
+
|
4
|
+
DEFAULT_NAMESPACE = "e3dd811dd3bbe49e630a"
|
5
|
+
DEFAULT_ROTATION_EXP = 12 # 2^12 = ~68 minutes
|
6
|
+
|
7
|
+
attr_reader :name,
|
8
|
+
:rotation_exp,
|
9
|
+
:namespace,
|
10
|
+
:instance,
|
11
|
+
:beacon_private_key,
|
12
|
+
:beacon_keypair,
|
13
|
+
:beacon_time_zero
|
14
|
+
|
15
|
+
def initialize(name:,
|
16
|
+
rotation_exp: nil,
|
17
|
+
namespace: nil,
|
18
|
+
instance: nil,
|
19
|
+
beacon_private_key: nil)
|
20
|
+
@name = name
|
21
|
+
@rotation_exp = (rotation_exp || DEFAULT_ROTATION_EXP).to_i
|
22
|
+
@namespace = namespace || DEFAULT_NAMESPACE
|
23
|
+
@instance = instance || random_instance
|
24
|
+
@beacon_private_key = beacon_private_key || EphemeralCalc::KeyPair.generate_private_key
|
25
|
+
@beacon_keypair = EphemeralCalc::KeyPair.new(@beacon_private_key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def api_client
|
29
|
+
@api_client ||= ProximityBeacon::Client.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def eid_params
|
33
|
+
@eid_params ||= api_client.eidparams
|
34
|
+
end
|
35
|
+
|
36
|
+
def resolver_public_key
|
37
|
+
Base64.decode64(eid_params["serviceEcdhPublicKey"])
|
38
|
+
end
|
39
|
+
|
40
|
+
def identity_key
|
41
|
+
beacon_keypair.identity_key(resolver_public_key: resolver_public_key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def encryptor
|
45
|
+
@encryptor ||= EphemeralCalc::Encryptor.new(identity_key, rotation_exp)
|
46
|
+
end
|
47
|
+
|
48
|
+
def initial_eid
|
49
|
+
[encryptor.get_identifier(0)].pack("H*")
|
50
|
+
end
|
51
|
+
|
52
|
+
def register
|
53
|
+
beacon = ProximityBeacon::Beacon.new(
|
54
|
+
ephemeral_id_registration: {
|
55
|
+
beaconEcdhPublicKey: Base64.strict_encode64(beacon_keypair.public_key),
|
56
|
+
serviceEcdhPublicKey: eid_params["serviceEcdhPublicKey"],
|
57
|
+
rotationPeriodExponent: rotation_exp,
|
58
|
+
initialClockValue: encryptor.beacon_time,
|
59
|
+
initialEid: Base64.strict_encode64(initial_eid)
|
60
|
+
},
|
61
|
+
advertised_id: ProximityBeacon::AdvertisedId.new(
|
62
|
+
eddystone_ids: [namespace, instance]
|
63
|
+
),
|
64
|
+
status: "ACTIVE",
|
65
|
+
description: self.name,
|
66
|
+
)
|
67
|
+
api_client.beacons.register(beacon)
|
68
|
+
end
|
69
|
+
|
70
|
+
def as_yaml
|
71
|
+
{
|
72
|
+
identity_key: identity_key,
|
73
|
+
rotation_exp: rotation_exp,
|
74
|
+
initial_time: encryptor.initial_time,
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_yaml
|
79
|
+
as_yaml.to_yaml
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def random_instance
|
85
|
+
SecureRandom.random_bytes(6).unpack("H*")[0]
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
data/lib/ephemeral_calc.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
+
require "proximity_beacon"
|
2
|
+
|
1
3
|
require "ephemeral_calc/version"
|
2
4
|
require "ephemeral_calc/curve25519"
|
3
5
|
require "ephemeral_calc/encryptor"
|
4
6
|
require "ephemeral_calc/key_pair"
|
5
|
-
require "ephemeral_calc/
|
6
|
-
require "ephemeral_calc/google_api/credentials"
|
7
|
-
require "ephemeral_calc/google_api/request"
|
8
|
-
require "ephemeral_calc/google_api/client"
|
7
|
+
require "ephemeral_calc/registration"
|
9
8
|
|
10
9
|
module EphemeralCalc
|
11
10
|
# Your code goes here...
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ephemeral_calc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radius Networks
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: proximity_beacon
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.3
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -106,11 +120,8 @@ files:
|
|
106
120
|
- ext/curve25519/extconf.rb
|
107
121
|
- lib/ephemeral_calc.rb
|
108
122
|
- lib/ephemeral_calc/encryptor.rb
|
109
|
-
- lib/ephemeral_calc/google_api/client.rb
|
110
|
-
- lib/ephemeral_calc/google_api/credentials.rb
|
111
|
-
- lib/ephemeral_calc/google_api/oauth.rb
|
112
|
-
- lib/ephemeral_calc/google_api/request.rb
|
113
123
|
- lib/ephemeral_calc/key_pair.rb
|
124
|
+
- lib/ephemeral_calc/registration.rb
|
114
125
|
- lib/ephemeral_calc/version.rb
|
115
126
|
homepage: https://github.com/RadiusNetworks/ephemeral_calc
|
116
127
|
licenses: []
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'uri'
|
3
|
-
require 'net/http'
|
4
|
-
require 'base64'
|
5
|
-
|
6
|
-
module EphemeralCalc
|
7
|
-
module GoogleAPI
|
8
|
-
class Client
|
9
|
-
|
10
|
-
PROXIMITY_BEACON_ROOT = "https://proximitybeacon.googleapis.com/v1beta1/"
|
11
|
-
EIDPARAMS_URI = URI(PROXIMITY_BEACON_ROOT + "eidparams")
|
12
|
-
BEACON_REGISTER_URI = URI(PROXIMITY_BEACON_ROOT + "beacons:register")
|
13
|
-
|
14
|
-
attr_accessor :credentials
|
15
|
-
|
16
|
-
def initialize(credentials = OAuth.new.get_credentials)
|
17
|
-
self.credentials = credentials
|
18
|
-
end
|
19
|
-
|
20
|
-
def eidparams
|
21
|
-
response = Request.get(EIDPARAMS_URI, credentials)
|
22
|
-
# response = request(:get, EIDPARAMS_URI, credentials.access_token)
|
23
|
-
return JSON.parse(response.body)
|
24
|
-
end
|
25
|
-
|
26
|
-
def register_eid(beacon_public_key, rotation_exp, initial_eid, initial_clock, uid_bytes)
|
27
|
-
service_public_key_base64 = get_eidparams["serviceEcdhPublicKey"]
|
28
|
-
response = Request.post(BEACON_REGISTER_URI, credentials) {|request|
|
29
|
-
request.add_field "Content-Type", "application/json"
|
30
|
-
request.body = {
|
31
|
-
ephemeralIdRegistration: {
|
32
|
-
beaconEcdhPublicKey: Base64.strict_encode64(beacon_public_key),
|
33
|
-
serviceEcdhPublicKey: service_public_key_base64,
|
34
|
-
rotationPeriodExponent: rotation_exp,
|
35
|
-
initialClockValue: initial_clock,
|
36
|
-
initialEid: Base64.strict_encode64(initial_eid)
|
37
|
-
},
|
38
|
-
advertisedId: {
|
39
|
-
type: "EDDYSTONE",
|
40
|
-
id: Base64.strict_encode64(uid_bytes)
|
41
|
-
},
|
42
|
-
status: "ACTIVE",
|
43
|
-
description: "EphemeralCalc Registered EID"
|
44
|
-
}.to_json
|
45
|
-
}
|
46
|
-
JSON.parse(response.body)
|
47
|
-
end
|
48
|
-
|
49
|
-
def get_resource(resource_name)
|
50
|
-
uri = URI(PROXIMITY_BEACON_ROOT + resource_name)
|
51
|
-
response = Request.get(uri, credentials)
|
52
|
-
JSON.parse(response.body)
|
53
|
-
end
|
54
|
-
|
55
|
-
def getforobserved(eids, api_key = ENV["GOOGLE_API_KEY"])
|
56
|
-
uri = URI("#{PROXIMITY_BEACON_ROOT}beaconinfo:getforobserved?key=#{api_key}")
|
57
|
-
response = Request.post(uri) {|request|
|
58
|
-
observations = Array(eids).map {|eid|
|
59
|
-
{advertisedId: {type: "EDDYSTONE_EID", id: base64_eid(eid)}}
|
60
|
-
}
|
61
|
-
request.body = {
|
62
|
-
observations: observations,
|
63
|
-
namespacedTypes: "*",
|
64
|
-
}.to_json
|
65
|
-
request.add_field "Content-Type", "application/json"
|
66
|
-
}
|
67
|
-
JSON.parse(response.body)
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def base64_eid(eid)
|
73
|
-
if eid.size == 16
|
74
|
-
Base64.strict_encode64([eid].pack("H*"))
|
75
|
-
else
|
76
|
-
Base64.strict_encode64(eid)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
module EphemeralCalc
|
4
|
-
module GoogleAPI
|
5
|
-
class Credentials
|
6
|
-
|
7
|
-
DEFAULT_FILE_STORE = File.expand_path("~/.ephemeral_calc_google_credentials.yaml")
|
8
|
-
attr_accessor :access_token, :refresh_token, :expires_at
|
9
|
-
|
10
|
-
def self.from_file(file = DEFAULT_FILE_STORE)
|
11
|
-
return nil unless File.exist?(file)
|
12
|
-
self.new YAML.load_file(file)
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(opts = {})
|
16
|
-
# convert string keys to symbols
|
17
|
-
opts = opts.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
18
|
-
|
19
|
-
self.access_token = opts[:access_token]
|
20
|
-
self.refresh_token = opts[:refresh_token]
|
21
|
-
self.expires_at = opts[:expires_at] || (Time.now + opts[:expires_in].to_i)
|
22
|
-
end
|
23
|
-
|
24
|
-
def save(file = DEFAULT_FILE_STORE)
|
25
|
-
data = {
|
26
|
-
access_token: access_token,
|
27
|
-
refresh_token: refresh_token,
|
28
|
-
expires_at: expires_at
|
29
|
-
}.to_yaml
|
30
|
-
File.open(file, 'w') {|f| f.write(data) }
|
31
|
-
end
|
32
|
-
|
33
|
-
def expired?
|
34
|
-
self.expires_at < Time.now
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'uri'
|
3
|
-
require 'net/http'
|
4
|
-
|
5
|
-
module EphemeralCalc
|
6
|
-
module GoogleAPI
|
7
|
-
class OAuth
|
8
|
-
|
9
|
-
SCOPES = [
|
10
|
-
"https://www.googleapis.com/auth/userlocation.beacon.registry",
|
11
|
-
"https://www.googleapis.com/auth/cloud-platform",
|
12
|
-
]
|
13
|
-
|
14
|
-
REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"
|
15
|
-
TOKEN_URI = URI("https://www.googleapis.com/oauth2/v4/token")
|
16
|
-
|
17
|
-
attr_accessor :client_id, :secret
|
18
|
-
|
19
|
-
def initialize(client_id = ENV["GOOGLE_CLIENT_ID"], secret = ENV["GOOGLE_CLIENT_SECRET"])
|
20
|
-
if client_id.nil? || secret.nil?
|
21
|
-
raise ArgumentError, "No Google Client ID or Secret was set. These can set in the environment variables \"GOOGLE_CLIENT_ID\" and \"GOOGLE_CLIENT_SECRET\" respectively. Credentials must be created for your project at \"https://console.developers.google.com/apis/credentials\"."
|
22
|
-
end
|
23
|
-
self.client_id = client_id
|
24
|
-
self.secret = secret
|
25
|
-
end
|
26
|
-
|
27
|
-
def get_code
|
28
|
-
puts("Performing OAuth with Google...")
|
29
|
-
if RUBY_PLATFORM =~ /darwin/
|
30
|
-
system("open \"#{url}\"")
|
31
|
-
else
|
32
|
-
puts("Open this URL in your browser: \"#{url}\"\n\n")
|
33
|
-
end
|
34
|
-
printf "Copy and paste code from web browser here: "
|
35
|
-
_code = STDIN.gets.chomp
|
36
|
-
end
|
37
|
-
|
38
|
-
def get_credentials(old_credentials = Credentials.from_file)
|
39
|
-
return old_credentials if old_credentials && !old_credentials.expired?
|
40
|
-
response = Request.post(TOKEN_URI) {|request|
|
41
|
-
request.body = hash_to_params( token_request_params(old_credentials) )
|
42
|
-
}
|
43
|
-
json = JSON.parse(response.body)
|
44
|
-
credentials = Credentials.new(json)
|
45
|
-
if old_credentials
|
46
|
-
credentials.refresh_token = old_credentials.refresh_token
|
47
|
-
end
|
48
|
-
return credentials
|
49
|
-
end
|
50
|
-
|
51
|
-
def url
|
52
|
-
params = hash_to_params(
|
53
|
-
scope: SCOPES.join("%20"),
|
54
|
-
redirect_uri: REDIRECT_URI,
|
55
|
-
response_type: "code",
|
56
|
-
client_id: client_id,
|
57
|
-
)
|
58
|
-
"https://accounts.google.com/o/oauth2/v2/auth?#{params}"
|
59
|
-
end
|
60
|
-
|
61
|
-
def token_request_params(old_credentials)
|
62
|
-
if old_credentials == nil
|
63
|
-
{
|
64
|
-
code: get_code,
|
65
|
-
client_id: client_id,
|
66
|
-
client_secret: secret,
|
67
|
-
redirect_uri: REDIRECT_URI,
|
68
|
-
grant_type: "authorization_code",
|
69
|
-
}
|
70
|
-
else
|
71
|
-
# this is a refresh of the old credentials
|
72
|
-
{
|
73
|
-
refresh_token: old_credentials.refresh_token,
|
74
|
-
client_id: client_id,
|
75
|
-
client_secret: secret,
|
76
|
-
grant_type: "refresh_token",
|
77
|
-
}
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def hash_to_params(hash)
|
82
|
-
hash.map {|k,v| "#{k}=#{v}"}.join("&")
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'uri'
|
3
|
-
require 'net/http'
|
4
|
-
require 'base64'
|
5
|
-
|
6
|
-
module EphemeralCalc
|
7
|
-
module GoogleAPI
|
8
|
-
class Request
|
9
|
-
extend Forwardable
|
10
|
-
|
11
|
-
attr_accessor :method, :uri, :credentials
|
12
|
-
def_delegators :request, :add_field, :body=
|
13
|
-
|
14
|
-
def self.get(uri, credentials = nil)
|
15
|
-
result = self.new(:get, uri, credentials)
|
16
|
-
result.perform {|r| yield r if block_given? }
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.post(uri, credentials = nil)
|
20
|
-
result = self.new(:post, uri, credentials)
|
21
|
-
result.perform {|r| yield r if block_given? }
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(method, uri, credentials = nil)
|
25
|
-
self.method = method
|
26
|
-
self.uri = uri
|
27
|
-
self.credentials = credentials
|
28
|
-
yield self if block_given?
|
29
|
-
end
|
30
|
-
|
31
|
-
def perform
|
32
|
-
http_opts = {use_ssl: true}
|
33
|
-
response = Net::HTTP.start(uri.host, uri.port, http_opts) do |http|
|
34
|
-
add_field "Authorization", "Bearer #{credentials.access_token}" if credentials
|
35
|
-
add_field "Accept", "application/json"
|
36
|
-
yield self if block_given?
|
37
|
-
http.request request
|
38
|
-
end
|
39
|
-
if (200..299).include?(response.code.to_i)
|
40
|
-
return response
|
41
|
-
else
|
42
|
-
raise RequestError.new(response.code.to_i), "Error #{response.code} (#{response.msg}) - #{uri}\n#{response.body}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def request
|
49
|
-
@request ||=
|
50
|
-
begin
|
51
|
-
case method
|
52
|
-
when :get
|
53
|
-
Net::HTTP::Get.new uri.request_uri
|
54
|
-
when :post
|
55
|
-
Net::HTTP::Post.new uri.request_uri
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class RequestError < StandardError
|
62
|
-
attr_accessor :code
|
63
|
-
def initialize(code)
|
64
|
-
self.code = code
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|