respoke 1.1.3
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/.editorconfig +17 -0
- data/.gitignore +7 -0
- data/.simplecov +6 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +93 -0
- data/Rakefile +32 -0
- data/lib/respoke.rb +7 -0
- data/lib/respoke/client.rb +265 -0
- data/lib/respoke/errors.rb +9 -0
- data/lib/respoke/response.rb +9 -0
- data/lib/respoke/response/session_token.rb +12 -0
- data/lib/respoke/response/session_token_id.rb +27 -0
- data/lib/respoke/role.rb +20 -0
- data/lib/respoke/version.rb +4 -0
- data/respoke.gemspec +34 -0
- data/test/spec/brokered_auth_spec.rb +89 -0
- data/test/spec/role_spec.rb +44 -0
- data/test/test_config.example.yml +6 -0
- data/test/test_config.yml.enc +0 -0
- data/test/test_helper.rb +26 -0
- data/test/unit/client_test.rb +43 -0
- data/test/unit/respoke_test.rb +7 -0
- data/test/unit/response/session_token_id_test.rb +40 -0
- data/test/unit/response/session_token_test.rb +9 -0
- data/test/vcr_cassettes/app_token_request.yml +99 -0
- data/test/vcr_cassettes/create_role.yml +51 -0
- data/test/vcr_cassettes/delete_a_role.yml +143 -0
- data/test/vcr_cassettes/find_role.yml +97 -0
- data/test/vcr_cassettes/session_token_id_request.yml +51 -0
- data/test/vcr_cassettes/session_token_request.yml +51 -0
- data/test/vcr_cassettes/update_role.yml +145 -0
- metadata +276 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Respoke
|
4
|
+
module Response
|
5
|
+
# A response object for session token requests.
|
6
|
+
#
|
7
|
+
# @attr token [String] The token for use as an App-Token.
|
8
|
+
# @attr message [String] Token request status information.
|
9
|
+
class SessionToken < Hashie::Mash
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Respoke
|
4
|
+
module Response
|
5
|
+
# A response object for token requests.
|
6
|
+
#
|
7
|
+
# @attr tokenId [String] Token ID used to request an App-Token.
|
8
|
+
# @attr appId [String] App ID App-Token is associated with.
|
9
|
+
# @attr roleId [String] Role ID App-Token is assigned.
|
10
|
+
# @attr endpointId [String] Endpoint ID App-Token is for.
|
11
|
+
# @attr ttl [Number] Number of seconds App-Token is valid for.
|
12
|
+
# @attr createdAt [DateTime] When the token request was made.
|
13
|
+
# @attr expiryTime [DateTime] When the token expires.
|
14
|
+
# @attr createTime [DateTime] When the token was created.
|
15
|
+
class SessionTokenId < Hashie::Mash
|
16
|
+
include Hashie::Extensions::Coercion
|
17
|
+
|
18
|
+
coerce_key :createdAt, ->(time) do
|
19
|
+
Time.parse(time).getutc
|
20
|
+
end
|
21
|
+
|
22
|
+
coerce_key :expiryTime, :createTime, ->(timestamp) do
|
23
|
+
Time.at(timestamp).getutc
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/respoke/role.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Respoke
|
2
|
+
class Role
|
3
|
+
attr_reader :id, :name
|
4
|
+
attr_accessor :rules
|
5
|
+
def initialize(client, id:, name:, **rules)
|
6
|
+
@client = client
|
7
|
+
@id = id
|
8
|
+
@name = name
|
9
|
+
@rules = rules
|
10
|
+
end
|
11
|
+
|
12
|
+
def save
|
13
|
+
response = @client.update_role(id: @id, rules: @rules)
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete
|
17
|
+
response = @client.delete_role(id: @id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/respoke.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'respoke/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'respoke'
|
8
|
+
spec.version = Respoke::VERSION
|
9
|
+
spec.date = Time.now.strftime('%Y-%m-%d')
|
10
|
+
spec.authors = ['Matthew Turney']
|
11
|
+
spec.email = ['mturney@respoke.io']
|
12
|
+
spec.summary = %q{Wrapper library for the Respoke API.}
|
13
|
+
spec.homepage = 'https://respoke.io'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_dependency 'faraday', '~> 0.9'
|
21
|
+
spec.add_dependency 'faraday_middleware', '~> 0.9'
|
22
|
+
spec.add_dependency 'hashie', '~> 3.3.2'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
spec.add_development_dependency 'minitest'
|
27
|
+
spec.add_development_dependency 'minitest-reporters'
|
28
|
+
spec.add_development_dependency 'yard'
|
29
|
+
spec.add_development_dependency 'simplecov'
|
30
|
+
spec.add_development_dependency 'ruby-lint'
|
31
|
+
spec.add_development_dependency 'vcr'
|
32
|
+
spec.add_development_dependency 'webmock'
|
33
|
+
spec.add_development_dependency 'timecop'
|
34
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe 'Brokered authentication' do
|
4
|
+
subject { client }
|
5
|
+
|
6
|
+
describe 'when using App-Secret' do
|
7
|
+
let :client do
|
8
|
+
Respoke::Client.new(app_secret: TestConfig.app_secret)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'requests token ID' do
|
12
|
+
response = nil
|
13
|
+
|
14
|
+
VCR.use_cassette 'session_token_id_request' do
|
15
|
+
response = subject.request_session_token_id(
|
16
|
+
appId: TestConfig.app_id,
|
17
|
+
endpointId: 'foo-bar',
|
18
|
+
roleId: TestConfig.role_id,
|
19
|
+
ttl: 60
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
assert response.tokenId?
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'and already given a session token ID' do
|
27
|
+
let :token_id do
|
28
|
+
token_id = ''
|
29
|
+
|
30
|
+
VCR.use_cassette 'session_token_id_request' do
|
31
|
+
token_id = subject.request_session_token_id(
|
32
|
+
appId: TestConfig.app_id,
|
33
|
+
endpointId: 'foo-bar',
|
34
|
+
roleId: TestConfig.role_id,
|
35
|
+
ttl: 60 # this is short since it's only needed in the test
|
36
|
+
).tokenId
|
37
|
+
end
|
38
|
+
|
39
|
+
token_id
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'requests App-Token using session token ID' do
|
43
|
+
response = nil
|
44
|
+
|
45
|
+
VCR.use_cassette 'session_token_request' do
|
46
|
+
response = subject.request_session_token(
|
47
|
+
appId: TestConfig.app_id,
|
48
|
+
tokenId: token_id,
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
assert response.token?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'requests an App-Token in one step' do
|
57
|
+
token = ''
|
58
|
+
|
59
|
+
VCR.use_cassette 'app_token_request' do
|
60
|
+
token = subject.app_token(
|
61
|
+
appId: TestConfig.app_id,
|
62
|
+
endpointId: 'foo-bar',
|
63
|
+
roleId: TestConfig.role_id,
|
64
|
+
ttl: 60
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
assert_instance_of String, token
|
69
|
+
refute_equal '', token
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'when App-Token has already been set' do
|
73
|
+
before do
|
74
|
+
VCR.use_cassette 'app_token_request' do
|
75
|
+
@expected_app_token = subject.app_token(
|
76
|
+
appId: TestConfig.app_id,
|
77
|
+
endpointId: 'foo-bar',
|
78
|
+
roleId: TestConfig.role_id,
|
79
|
+
ttl: 60
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'returns that token' do
|
85
|
+
assert_equal @expected_app_token, subject.app_token
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
|
5
|
+
describe "Roles" do
|
6
|
+
let :client do
|
7
|
+
Respoke::Client.new(app_secret: TestConfig.app_secret)
|
8
|
+
end
|
9
|
+
|
10
|
+
let :existing_role do
|
11
|
+
client.create_role(name: SecureRandom::uuid(), rules: {})
|
12
|
+
end
|
13
|
+
|
14
|
+
it "creates a role" do
|
15
|
+
VCR.use_cassette 'create_role' do
|
16
|
+
role_name = SecureRandom::uuid()
|
17
|
+
role = client.create_role(name: role_name, rules: { mediaRelay: false })
|
18
|
+
assert !role.id.nil?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "finds a role" do
|
23
|
+
VCR.use_cassette 'find_role' do
|
24
|
+
response = client.find_role(id: existing_role.id)
|
25
|
+
assert (response.name == existing_role.name) && (existing_role.id == existing_role.id)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "updates a role" do
|
30
|
+
VCR.use_cassette 'update_role' do
|
31
|
+
assert existing_role.rules[:mediaRelay] == false
|
32
|
+
existing_role.rules[:mediaRelay]=true
|
33
|
+
existing_role.save
|
34
|
+
assert (client.find_role(id: existing_role.id).rules[:mediaRelay] == true)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "deletes a role" do
|
39
|
+
VCR.use_cassette 'delete_a_role' do
|
40
|
+
existing_role.delete
|
41
|
+
assert client.find_role(id: existing_role.id).nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
Binary file
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'hashie'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require 'minitest/reporters'
|
8
|
+
|
9
|
+
require 'simplecov' if ENV["COVERAGE"]
|
10
|
+
|
11
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
12
|
+
require 'respoke'
|
13
|
+
|
14
|
+
Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
|
15
|
+
|
16
|
+
TestConfig = Hashie::Mash.load(File.expand_path('test_config.yml', __dir__))
|
17
|
+
|
18
|
+
VCR.configure do |config|
|
19
|
+
# Due to a bug in VCR faraday middleware we must use webmock. A fix has been
|
20
|
+
# merged (https://github.com/vcr/vcr/pull/439) but it does not have a tagged
|
21
|
+
# release yet.
|
22
|
+
config.hook_into :webmock
|
23
|
+
config.cassette_library_dir = 'test/vcr_cassettes'
|
24
|
+
config.default_cassette_options = { :record => :once }
|
25
|
+
config.filter_sensitive_data('<APP_SECRET>') { TestConfig.app_secret }
|
26
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Respoke::TestClient < MiniTest::Test
|
4
|
+
def setup
|
5
|
+
@client = Respoke::Client.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_can_create_new_client
|
9
|
+
assert_instance_of Respoke::Client, @client
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_can_set_app_secret_on_initialization
|
13
|
+
secret = 'foo'
|
14
|
+
client = Respoke::Client.new(app_secret: secret)
|
15
|
+
|
16
|
+
assert_equal secret, client.app_secret
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_cannot_set_app_secret_by_attribute
|
20
|
+
secret = 'foo'
|
21
|
+
|
22
|
+
assert_raises NoMethodError do
|
23
|
+
@client.app_secret = secret
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_has_default_base_url
|
28
|
+
assert_equal Respoke::Client::DEFAULT_BASE_URL, @client.base_url
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_can_override_base_url
|
32
|
+
url = 'https://localhost:2000'
|
33
|
+
client = Respoke::Client.new(base_url: url)
|
34
|
+
|
35
|
+
assert_equal url, client.base_url
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_cannot_set_base_url_by_attribute
|
39
|
+
assert_raises NoMethodError do
|
40
|
+
@client.base_url = 'https://localhost:2000'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Respoke::Response::TestSessionTokenId < Minitest::Test
|
4
|
+
def setup
|
5
|
+
@klass = Respoke::Response::SessionTokenId
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_can_create_new_instance
|
9
|
+
response = @klass.new
|
10
|
+
|
11
|
+
assert_instance_of @klass, response
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_coerces_createdAt_to_utc_Time
|
15
|
+
response = @klass.new(
|
16
|
+
createdAt: '2015-01-02T21:30:57.714Z'
|
17
|
+
)
|
18
|
+
|
19
|
+
assert_instance_of Time, response.createdAt
|
20
|
+
assert response.createdAt.utc?
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_coerces_expiryTime_to_utc_Time
|
24
|
+
response = @klass.new(
|
25
|
+
expiryTime: 1420320657
|
26
|
+
)
|
27
|
+
|
28
|
+
assert_instance_of Time, response.expiryTime
|
29
|
+
assert response.expiryTime.utc?
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_coerces_createTime_to_utc_Time
|
33
|
+
response = @klass.new(
|
34
|
+
createTime: 1420320657
|
35
|
+
)
|
36
|
+
|
37
|
+
assert_instance_of Time, response.createTime
|
38
|
+
assert response.createTime.utc?
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://api.respoke.io/v1/tokens
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: '{"appId":"0dfcfe78-c4af-497f-88f6-c6b3a8151fb3","endpointId":"foo-bar","roleId":"56BD864A-3474-4D41-A3E7-1577078B63D5","ttl":86400}'
|
9
|
+
headers:
|
10
|
+
App-Secret:
|
11
|
+
- "<APP_SECRET>"
|
12
|
+
User-Agent:
|
13
|
+
- Faraday v0.9.0
|
14
|
+
Content-Type:
|
15
|
+
- application/json
|
16
|
+
Accept-Encoding:
|
17
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
18
|
+
Accept:
|
19
|
+
- "*/*"
|
20
|
+
response:
|
21
|
+
status:
|
22
|
+
code: 200
|
23
|
+
message: OK
|
24
|
+
headers:
|
25
|
+
Server:
|
26
|
+
- nginx
|
27
|
+
Date:
|
28
|
+
- Fri, 02 Jan 2015 21:30:58 GMT
|
29
|
+
Content-Type:
|
30
|
+
- application/json; charset=utf-8
|
31
|
+
Transfer-Encoding:
|
32
|
+
- chunked
|
33
|
+
Connection:
|
34
|
+
- keep-alive
|
35
|
+
Vary:
|
36
|
+
- Accept-Encoding
|
37
|
+
- Accept-Encoding
|
38
|
+
Request-Id:
|
39
|
+
- 5b39afb9-c629-434f-861e-aadc75319f4b
|
40
|
+
Ratelimit-Limit:
|
41
|
+
- '10'
|
42
|
+
Ratelimit-Time-Units:
|
43
|
+
- seconds
|
44
|
+
Ratelimit-Remaining:
|
45
|
+
- '7'
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: '{"appId":"0dfcfe78-c4af-497f-88f6-c6b3a8151fb3","endpointId":"foo-bar","roleId":"56BD864A-3474-4D41-A3E7-1577078B63D5","accountId":"9628FFD0-54E8-402C-A979-368B03EC63D9","createTime":1420234258,"expiryTime":1420320658,"id":"E44902BA-639B-4EAD-9C88-CD846146BB19","forDevelopment":false,"createdAt":"2015-01-02T21:30:58.539Z","tokenId":"E44902BA-639B-4EAD-9C88-CD846146BB19"}'
|
49
|
+
http_version:
|
50
|
+
recorded_at: Fri, 02 Jan 2015 21:30:58 GMT
|
51
|
+
- request:
|
52
|
+
method: post
|
53
|
+
uri: https://api.respoke.io/v1/session-tokens
|
54
|
+
body:
|
55
|
+
encoding: UTF-8
|
56
|
+
string: '{"appId":"0dfcfe78-c4af-497f-88f6-c6b3a8151fb3","tokenId":"E44902BA-639B-4EAD-9C88-CD846146BB19"}'
|
57
|
+
headers:
|
58
|
+
App-Secret:
|
59
|
+
- "<APP_SECRET>"
|
60
|
+
User-Agent:
|
61
|
+
- Faraday v0.9.0
|
62
|
+
Content-Type:
|
63
|
+
- application/json
|
64
|
+
Accept-Encoding:
|
65
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
66
|
+
Accept:
|
67
|
+
- "*/*"
|
68
|
+
response:
|
69
|
+
status:
|
70
|
+
code: 200
|
71
|
+
message: OK
|
72
|
+
headers:
|
73
|
+
Server:
|
74
|
+
- nginx
|
75
|
+
Date:
|
76
|
+
- Fri, 02 Jan 2015 21:30:58 GMT
|
77
|
+
Content-Type:
|
78
|
+
- application/json; charset=utf-8
|
79
|
+
Transfer-Encoding:
|
80
|
+
- chunked
|
81
|
+
Connection:
|
82
|
+
- keep-alive
|
83
|
+
Vary:
|
84
|
+
- Accept-Encoding
|
85
|
+
- Accept-Encoding
|
86
|
+
Request-Id:
|
87
|
+
- 9a985440-76b2-4e83-9528-ddf22414e1cf
|
88
|
+
Ratelimit-Limit:
|
89
|
+
- '10'
|
90
|
+
Ratelimit-Time-Units:
|
91
|
+
- seconds
|
92
|
+
Ratelimit-Remaining:
|
93
|
+
- '6'
|
94
|
+
body:
|
95
|
+
encoding: UTF-8
|
96
|
+
string: '{"message":"Authorization successful","token":"1834AD29-F08B-43F7-91F1-52EF33814589"}'
|
97
|
+
http_version:
|
98
|
+
recorded_at: Fri, 02 Jan 2015 21:30:58 GMT
|
99
|
+
recorded_with: VCR 2.9.3
|