playlyfe 0.2.2 → 0.4.5
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.
- data/lib/playlyfe.rb +175 -59
- data/test/test.rb +119 -13
- metadata +32 -24
- data/lib/access_token.rb +0 -177
- data/lib/base.rb +0 -16
- data/lib/client.rb +0 -155
- data/lib/client_credentials.rb +0 -37
- data/lib/error.rb +0 -24
- data/lib/response.rb +0 -81
- data/lib/strategy.rb +0 -73
data/lib/playlyfe.rb
CHANGED
@@ -1,86 +1,202 @@
|
|
1
|
+
require 'uri'
|
1
2
|
require 'json'
|
2
|
-
require '
|
3
|
-
require 'client'
|
4
|
-
require 'base'
|
5
|
-
require 'strategy'
|
6
|
-
require 'client_credentials'
|
7
|
-
require 'access_token'
|
8
|
-
require 'response'
|
3
|
+
require 'rest_client'
|
9
4
|
|
10
|
-
class
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
5
|
+
class PlaylyfeError < StandardError
|
6
|
+
attr_accessor :name, :message
|
7
|
+
def initialize(res)
|
8
|
+
message = []
|
9
|
+
begin
|
10
|
+
res = JSON.parse(res)
|
11
|
+
@name = res['error']
|
12
|
+
@message = res['error_description']
|
13
|
+
message << "#{@code}: #{@description}"
|
14
|
+
rescue => e
|
15
|
+
end
|
16
|
+
super(message.join("\n"))
|
19
17
|
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Playlyfe
|
21
|
+
@@api = 'https://api.playlyfe.com/v1'
|
20
22
|
|
21
23
|
# You can initiate a client by giving the client_id and client_secret params
|
22
24
|
# This will authorize a client and get the token
|
25
|
+
#
|
26
|
+
# @param [Hash] options the options to make the request with
|
27
|
+
# @param options
|
28
|
+
# [Boolean] :type where where type can be 'code', 'client' for
|
29
|
+
# for the oauth2 auth code flow and client credentials flow
|
30
|
+
# [lambda] :store a method that persists the access_token into
|
31
|
+
# a database
|
32
|
+
# [lambda] :retrieve a method that is used by the sdk internally
|
33
|
+
# to read the access_token and use it in all your requests
|
23
34
|
def self.init(options = {})
|
24
35
|
puts 'Playlyfe Initializing...............................................'
|
36
|
+
if options[:type].nil?
|
37
|
+
err = PlaylyfeError.new("")
|
38
|
+
err.name = 'init_failed'
|
39
|
+
err.message = "You must pass in a type whether 'client' for client credentials flow or 'code' for auth code flow"
|
40
|
+
raise err
|
41
|
+
end
|
42
|
+
@@type = options[:type]
|
43
|
+
@@id = options[:client_id]
|
44
|
+
@@secret = options[:client_secret]
|
45
|
+
@@store = options[:store]
|
46
|
+
@@retrieve = options[:retrieve]
|
47
|
+
if @@store.nil?
|
48
|
+
@@store = lambda { |token| puts 'Storing Token' }
|
49
|
+
end
|
50
|
+
if @@type == 'client'
|
51
|
+
self.get_access_token()
|
52
|
+
else
|
53
|
+
if options[:redirect_uri].nil?
|
54
|
+
err = PlaylyfeError.new("")
|
55
|
+
err.name = 'init_failed'
|
56
|
+
err.message = 'You must pass in a redirect_uri for the auth code flow'
|
57
|
+
raise err
|
58
|
+
else
|
59
|
+
puts 'CLIENT'
|
60
|
+
#RestClient.get("https://playlyfe.com/auth?redirect_uri=#{options[:redirect_uri]}&response_type=code&client_id=#{@@id}")
|
61
|
+
#:authorize_url =>
|
62
|
+
#'response_type' => 'code', 'client_id' => @@id
|
63
|
+
#auth_url = @@client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth2/callback')
|
64
|
+
#@@client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth2/callback') #check query.code then make post request
|
65
|
+
end
|
66
|
+
end
|
67
|
+
#RestClient.log = Logger.new(STDOUT)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.get_access_token
|
71
|
+
puts 'Getting Access Token'
|
25
72
|
begin
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
:
|
30
|
-
:
|
31
|
-
|
73
|
+
access_token = RestClient.post('https://playlyfe.com/auth/token',
|
74
|
+
{
|
75
|
+
:client_id => @@id,
|
76
|
+
:client_secret => @@secret,
|
77
|
+
:grant_type => 'client_credentials'
|
78
|
+
}.to_json,
|
79
|
+
:content_type => :json,
|
80
|
+
:accept => :json
|
32
81
|
)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
82
|
+
access_token = JSON.parse(access_token)
|
83
|
+
expires_at ||= Time.now.to_i + access_token['expires_in']
|
84
|
+
access_token.delete('expires_in')
|
85
|
+
access_token['expires_at'] = expires_at
|
86
|
+
@@store.call access_token
|
87
|
+
if @@retrieve.nil?
|
88
|
+
@@retrieve = lambda { return access_token }
|
89
|
+
end
|
90
|
+
rescue => e
|
91
|
+
raise PlaylyfeError.new(e.response)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.check_expired(access_token)
|
96
|
+
if access_token['expires_at'] < Time.now.to_i
|
97
|
+
puts 'Access Token Expired'
|
98
|
+
self.get_access_token()
|
37
99
|
end
|
38
|
-
create_token()
|
39
100
|
end
|
40
101
|
|
41
|
-
def
|
42
|
-
|
102
|
+
# def refresh!(params = {})
|
103
|
+
# params.merge!(:client_id => @client.id,
|
104
|
+
# :client_secret => @client.secret,
|
105
|
+
# :grant_type => 'refresh_token',
|
106
|
+
# :refresh_token => refresh_token)
|
107
|
+
# new_token = @client.get_token(params)
|
108
|
+
# new_token.options = options
|
109
|
+
# new_token.refresh_token = refresh_token unless new_token.refresh_token
|
110
|
+
# new_token
|
111
|
+
# end
|
112
|
+
|
113
|
+
def self.login
|
43
114
|
end
|
44
115
|
|
45
116
|
def self.get(options = {})
|
46
|
-
options[:
|
47
|
-
options[:query] ||=
|
117
|
+
options[:route] ||= ''
|
118
|
+
options[:query] ||= {}
|
48
119
|
options[:raw] ||= false
|
120
|
+
|
121
|
+
access_token = @@retrieve.call
|
122
|
+
self.check_expired(access_token)
|
123
|
+
options[:query][:access_token] = access_token['access_token']
|
124
|
+
|
49
125
|
begin
|
50
|
-
|
126
|
+
res = RestClient.get("#{@@api}#{options[:route]}",
|
127
|
+
{:params => options[:query] }
|
128
|
+
)
|
51
129
|
if options[:raw] == true
|
52
|
-
return
|
53
|
-
|
54
|
-
|
55
|
-
if @@debug
|
56
|
-
puts "Playlyfe: GET #{@@api}#{options[:url]}?debug=true&player_id=#{options[:player]}&#{options[:query]}"
|
57
|
-
puts
|
58
|
-
puts json
|
59
|
-
end
|
60
|
-
return json
|
61
|
-
rescue OAuth2::Error => e
|
62
|
-
puts 'OAuth2 Error'
|
63
|
-
puts e.code
|
64
|
-
puts e.description
|
65
|
-
if e.code == 'invalid_token'
|
66
|
-
create_token()
|
67
|
-
get()
|
130
|
+
return res.body
|
131
|
+
else
|
132
|
+
return JSON.parse(res.body)
|
68
133
|
end
|
134
|
+
rescue => e
|
135
|
+
raise PlaylyfeError.new(e.response)
|
69
136
|
end
|
70
137
|
end
|
71
138
|
|
72
139
|
def self.post(options = {})
|
73
|
-
options[:
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
140
|
+
options[:route] ||= ''
|
141
|
+
options[:query] ||= {}
|
142
|
+
options[:body] ||= {}
|
143
|
+
|
144
|
+
access_token = @@retrieve.call
|
145
|
+
self.check_expired(access_token)
|
146
|
+
options[:query][:access_token] = access_token['access_token']
|
147
|
+
|
148
|
+
begin
|
149
|
+
res = RestClient.post("#{@@api}#{options[:route]}?#{self.hash_to_query(options[:query])}",
|
150
|
+
options[:body].to_json,
|
151
|
+
:content_type => :json,
|
152
|
+
:accept => :json
|
153
|
+
)
|
154
|
+
return JSON.parse(res.body)
|
155
|
+
rescue => e
|
156
|
+
raise PlaylyfeError.new(e.response)
|
83
157
|
end
|
84
|
-
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.patch(options = {})
|
161
|
+
options[:route] ||= ''
|
162
|
+
options[:query] ||= {}
|
163
|
+
options[:body] ||= {}
|
164
|
+
|
165
|
+
access_token = @@retrieve.call
|
166
|
+
self.check_expired(access_token)
|
167
|
+
options[:query][:access_token] = access_token['access_token']
|
168
|
+
|
169
|
+
begin
|
170
|
+
res = RestClient.patch("#{@@api}#{options[:route]}?#{self.hash_to_query(options[:query])}",
|
171
|
+
options[:body].to_json,
|
172
|
+
:content_type => :json,
|
173
|
+
:accept => :json
|
174
|
+
)
|
175
|
+
return JSON.parse(res.body)
|
176
|
+
rescue => e
|
177
|
+
raise PlaylyfeError.new(e.response)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.delete(options = {})
|
182
|
+
options[:route] ||= ''
|
183
|
+
options[:query] ||= {}
|
184
|
+
|
185
|
+
access_token = @@retrieve.call
|
186
|
+
self.check_expired(access_token)
|
187
|
+
options[:query][:access_token] = access_token['access_token']
|
188
|
+
|
189
|
+
begin
|
190
|
+
res = RestClient.delete("#{@@api}#{options[:route]}",
|
191
|
+
{:params => options[:query] }
|
192
|
+
)
|
193
|
+
JSON.parse(res.body)
|
194
|
+
rescue => e
|
195
|
+
raise PlaylyfeError.new(e.response)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.hash_to_query(hash)
|
200
|
+
return URI.encode(hash.map{|k,v| "#{k}=#{v}"}.join("&"))
|
85
201
|
end
|
86
202
|
end
|
data/test/test.rb
CHANGED
@@ -1,31 +1,137 @@
|
|
1
1
|
require 'test/unit'
|
2
|
+
require 'redis'
|
2
3
|
require 'playlyfe'
|
3
4
|
|
4
5
|
class PlaylyfeTest < Test::Unit::TestCase
|
5
6
|
|
6
|
-
def
|
7
|
+
def test_invalid_client
|
8
|
+
begin
|
9
|
+
Playlyfe.init(
|
10
|
+
client_id: "wrong_id",
|
11
|
+
client_secret: "wrong_secret",
|
12
|
+
type: 'client'
|
13
|
+
)
|
14
|
+
rescue PlaylyfeError => e
|
15
|
+
assert_equal e.name,'client_auth_fail'
|
16
|
+
assert_equal e.message, 'Client authentication failed'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_wrong_init
|
21
|
+
begin
|
22
|
+
Playlyfe.init(
|
23
|
+
client_id: "Zjc0MWU0N2MtODkzNS00ZWNmLWEwNmYtY2M1MGMxNGQ1YmQ4",
|
24
|
+
client_secret: "YzllYTE5NDQtNDMwMC00YTdkLWFiM2MtNTg0Y2ZkOThjYTZkMGIyNWVlNDAtNGJiMC0xMWU0LWI2NGEtYjlmMmFkYTdjOTI3"
|
25
|
+
)
|
26
|
+
rescue PlaylyfeError => e
|
27
|
+
assert_equal e.name, 'init_failed'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_wrong_api
|
32
|
+
begin
|
33
|
+
Playlyfe.init(
|
34
|
+
client_id: "Zjc0MWU0N2MtODkzNS00ZWNmLWEwNmYtY2M1MGMxNGQ1YmQ4",
|
35
|
+
client_secret: "YzllYTE5NDQtNDMwMC00YTdkLWFiM2MtNTg0Y2ZkOThjYTZkMGIyNWVlNDAtNGJiMC0xMWU0LWI2NGEtYjlmMmFkYTdjOTI3",
|
36
|
+
type: 'client'
|
37
|
+
)
|
38
|
+
Playlyfe.get(route: '/gege', query: { player_id: 'student1' })
|
39
|
+
rescue PlaylyfeError => e
|
40
|
+
assert_equal e.name,'route_not_found'
|
41
|
+
assert_equal e.message, 'This route does not exist'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_init_staging
|
7
46
|
Playlyfe.init(
|
8
|
-
client_id: "
|
9
|
-
client_secret: "
|
47
|
+
client_id: "Zjc0MWU0N2MtODkzNS00ZWNmLWEwNmYtY2M1MGMxNGQ1YmQ4",
|
48
|
+
client_secret: "YzllYTE5NDQtNDMwMC00YTdkLWFiM2MtNTg0Y2ZkOThjYTZkMGIyNWVlNDAtNGJiMC0xMWU0LWI2NGEtYjlmMmFkYTdjOTI3",
|
49
|
+
type: 'client'
|
10
50
|
)
|
11
|
-
|
12
|
-
|
13
|
-
players = Playlyfe.get(url: '/players')
|
51
|
+
players = Playlyfe.get(route: '/players', query: { player_id: 'student1', limit: 1 })
|
14
52
|
assert_not_nil players["data"]
|
15
53
|
assert_not_nil players["data"][0]
|
16
54
|
|
55
|
+
begin
|
56
|
+
assert_nil Playlyfe.get(route: '/player')
|
57
|
+
rescue PlaylyfeError => e
|
58
|
+
assert_equal e.message, "The 'player_id' parameter should be specified in the query"
|
59
|
+
end
|
60
|
+
|
17
61
|
player_id = 'student1'
|
18
|
-
player = Playlyfe.get(
|
62
|
+
player = Playlyfe.get(route: '/player', query: { player_id: player_id } )
|
19
63
|
assert_equal player["id"], "student1"
|
20
64
|
assert_equal player["alias"], "Student1"
|
21
65
|
assert_equal player["enabled"], true
|
22
66
|
|
23
|
-
|
24
|
-
|
67
|
+
Playlyfe.get(route: '/definitions/processes', query: { player_id: player_id } )
|
68
|
+
Playlyfe.get(route:'/definitions/teams', query: { player_id: player_id } )
|
69
|
+
Playlyfe.get(route: '/processes', query: { player_id: player_id } )
|
70
|
+
Playlyfe.get(route: '/teams', query: { player_id: player_id } )
|
71
|
+
|
72
|
+
processes = Playlyfe.get(route: '/processes', query: { player_id: 'student1', limit: 1, skip: 4 })
|
73
|
+
assert_equal processes["data"][0]["definition"], "module1"
|
74
|
+
assert_equal processes["data"].size, 1
|
75
|
+
|
76
|
+
new_process = Playlyfe.post(route: '/definitions/processes/module1', query: { player_id: player_id })
|
77
|
+
assert_equal new_process["definition"], "module1"
|
78
|
+
assert_equal new_process["state"], "ACTIVE"
|
79
|
+
|
80
|
+
patched_process = Playlyfe.patch(
|
81
|
+
route: "/processes/#{new_process['id']}",
|
82
|
+
query: { player_id: player_id },
|
83
|
+
body: { name: 'patched_process', access: 'PUBLIC' }
|
84
|
+
)
|
85
|
+
|
86
|
+
assert_equal patched_process['name'], 'patched_process'
|
87
|
+
assert_equal patched_process['access'], 'PUBLIC'
|
88
|
+
|
89
|
+
deleted_process = Playlyfe.delete(route: "/processes/#{new_process['id']}", query: { player_id: player_id })
|
90
|
+
assert_not_nil deleted_process['message']
|
91
|
+
end
|
25
92
|
|
26
|
-
|
27
|
-
Playlyfe.
|
28
|
-
|
29
|
-
|
93
|
+
def test_init_production
|
94
|
+
Playlyfe.init(
|
95
|
+
client_id: "N2Y4NjNlYTItODQzZi00YTQ0LTkzZWEtYTBiNTA2ODg3MDU4",
|
96
|
+
client_secret: "NDc3NTA0NmItMjBkZi00MjI2LWFhMjUtOTI0N2I1YTkxYjc2M2U3ZGI0MDAtNGQ1Mi0xMWU0LWJmZmUtMzkyZTdiOTYxYmMx",
|
97
|
+
type: 'client'
|
98
|
+
)
|
99
|
+
#player = Playlyfe.get(route: '/players', query: { player_id: 'l54328754bddc332e0021a847', limit: 1 })
|
100
|
+
#assert_equal player["data"][0]["email"], "peter@playlyfe.com"
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_store
|
104
|
+
redis = Redis.new
|
105
|
+
Playlyfe.init(
|
106
|
+
client_id: "Zjc0MWU0N2MtODkzNS00ZWNmLWEwNmYtY2M1MGMxNGQ1YmQ4",
|
107
|
+
client_secret: "YzllYTE5NDQtNDMwMC00YTdkLWFiM2MtNTg0Y2ZkOThjYTZkMGIyNWVlNDAtNGJiMC0xMWU0LWI2NGEtYjlmMmFkYTdjOTI3",
|
108
|
+
type: 'client',
|
109
|
+
store: lambda { |token| redis.set('token', JSON.generate(token)) },
|
110
|
+
retrieve: lambda { return JSON.parse(redis.get('token')) }
|
111
|
+
)
|
112
|
+
players = Playlyfe.get(route: '/players', query: { player_id: 'student1', limit: 1 })
|
113
|
+
assert_not_nil players["data"]
|
114
|
+
assert_not_nil players["data"][0]
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_auth_code_error
|
118
|
+
begin
|
119
|
+
Playlyfe.init(
|
120
|
+
client_id: "NGM2ZmYyNGQtNjViMy00YjQ0LWI0YTgtZTdmYWFlNDRkMmUx",
|
121
|
+
client_secret: "ZTQ0OWI4YTItYzE4ZC00MWQ5LTg3YjktMDI5ZjAxYTBkZmRiZGQ0NzI4OTAtNGQ1My0xMWU0LWJmZmUtMzkyZTdiOTYxYmMx",
|
122
|
+
type: 'code'
|
123
|
+
)
|
124
|
+
rescue PlaylyfeError => e
|
125
|
+
assert_equal e.name, 'init_failed'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_auth_code
|
130
|
+
Playlyfe.init(
|
131
|
+
client_id: "NGM2ZmYyNGQtNjViMy00YjQ0LWI0YTgtZTdmYWFlNDRkMmUx",
|
132
|
+
client_secret: "ZTQ0OWI4YTItYzE4ZC00MWQ5LTg3YjktMDI5ZjAxYTBkZmRiZGQ0NzI4OTAtNGQ1My0xMWU0LWJmZmUtMzkyZTdiOTYxYmMx",
|
133
|
+
type: 'code',
|
134
|
+
redirect_uri: 'https://playlyfe.com/v1/api'
|
135
|
+
)
|
30
136
|
end
|
31
137
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: playlyfe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,16 +9,16 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: rest_client
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.7.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,15 +26,15 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 1.7.2
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
31
|
+
name: json
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
35
|
- - '='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 1.8.1
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,23 +42,39 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - '='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 1.8.1
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: rake
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- - '
|
51
|
+
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
54
|
-
type: :
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- - '
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: redis
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
62
78
|
description: This gem can be used to interact with the playlyfe gamification platform
|
63
79
|
using oauth 2.0
|
64
80
|
email: peter@playlyfe.com
|
@@ -68,17 +84,9 @@ extra_rdoc_files: []
|
|
68
84
|
files:
|
69
85
|
- Rakefile
|
70
86
|
- lib/playlyfe.rb
|
71
|
-
- lib/access_token.rb
|
72
|
-
- lib/base.rb
|
73
|
-
- lib/client.rb
|
74
|
-
- lib/client_credentials.rb
|
75
|
-
- lib/error.rb
|
76
|
-
- lib/response.rb
|
77
|
-
- lib/strategy.rb
|
78
87
|
- test/test.rb
|
79
88
|
homepage: https://github.com/pyros2097/playlyfe-ruby-sdk
|
80
|
-
licenses:
|
81
|
-
- ApacheV2
|
89
|
+
licenses: []
|
82
90
|
post_install_message:
|
83
91
|
rdoc_options: []
|
84
92
|
require_paths:
|
@@ -100,7 +108,7 @@ rubyforge_project:
|
|
100
108
|
rubygems_version: 1.8.23
|
101
109
|
signing_key:
|
102
110
|
specification_version: 3
|
103
|
-
summary: The
|
111
|
+
summary: The Playlyfe Ruby SDK
|
104
112
|
test_files:
|
105
113
|
- test/test.rb
|
106
114
|
has_rdoc:
|
data/lib/access_token.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
module OAuth2
|
2
|
-
class AccessToken
|
3
|
-
attr_reader :client, :token, :expires_in, :expires_at, :params
|
4
|
-
attr_accessor :options, :refresh_token
|
5
|
-
|
6
|
-
def self.from_hash(client, hash)
|
7
|
-
new(client, hash.delete('access_token') || hash.delete(:access_token), hash)
|
8
|
-
end
|
9
|
-
|
10
|
-
class << self
|
11
|
-
# Initializes an AccessToken from a Hash
|
12
|
-
#
|
13
|
-
# @param [Client] the OAuth2::Client instance
|
14
|
-
# @param [Hash] a hash of AccessToken property values
|
15
|
-
# @return [AccessToken] the initalized AccessToken
|
16
|
-
def from_hash(client, hash)
|
17
|
-
new(client, hash.delete('access_token') || hash.delete(:access_token), hash)
|
18
|
-
end
|
19
|
-
|
20
|
-
# Initializes an AccessToken from a key/value application/x-www-form-urlencoded string
|
21
|
-
#
|
22
|
-
# @param [Client] client the OAuth2::Client instance
|
23
|
-
# @param [String] kvform the application/x-www-form-urlencoded string
|
24
|
-
# @return [AccessToken] the initalized AccessToken
|
25
|
-
def from_kvform(client, kvform)
|
26
|
-
from_hash(client, Rack::Utils.parse_query(kvform))
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Initalize an AccessToken
|
31
|
-
#
|
32
|
-
# @param [Client] client the OAuth2::Client instance
|
33
|
-
# @param [String] token the Access Token value
|
34
|
-
# @param [Hash] opts the options to create the Access Token with
|
35
|
-
# @option opts [String] :refresh_token (nil) the refresh_token value
|
36
|
-
# @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire
|
37
|
-
# @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire
|
38
|
-
# @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value
|
39
|
-
# one of :header, :body or :query
|
40
|
-
# @option opts [String] :header_format ('Bearer %s') the string format to use for the Authorization header
|
41
|
-
# @option opts [String] :param_name ('access_token') the parameter name to use for transmission of the
|
42
|
-
# Access Token value in :body or :query transmission mode
|
43
|
-
def initialize(client, token, opts = {})
|
44
|
-
@client = client
|
45
|
-
@token = token.to_s
|
46
|
-
[:refresh_token, :expires_in, :expires_at].each do |arg|
|
47
|
-
instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s))
|
48
|
-
end
|
49
|
-
@expires_in ||= opts.delete('expires')
|
50
|
-
@expires_in &&= @expires_in.to_i
|
51
|
-
@expires_at &&= @expires_at.to_i
|
52
|
-
@expires_at ||= Time.now.to_i + @expires_in if @expires_in
|
53
|
-
@options = {:mode => opts.delete(:mode) || :header,
|
54
|
-
:header_format => opts.delete(:header_format) || 'Bearer %s',
|
55
|
-
:param_name => opts.delete(:param_name) || 'access_token'}
|
56
|
-
@params = opts
|
57
|
-
end
|
58
|
-
|
59
|
-
# Indexer to additional params present in token response
|
60
|
-
#
|
61
|
-
# @param [String] key entry key to Hash
|
62
|
-
def [](key)
|
63
|
-
@params[key]
|
64
|
-
end
|
65
|
-
|
66
|
-
# Whether or not the token expires
|
67
|
-
#
|
68
|
-
# @return [Boolean]
|
69
|
-
def expires?
|
70
|
-
!!@expires_at # rubocop:disable DoubleNegation
|
71
|
-
end
|
72
|
-
|
73
|
-
# Whether or not the token is expired
|
74
|
-
#
|
75
|
-
# @return [Boolean]
|
76
|
-
def expired?
|
77
|
-
expires? && (expires_at < Time.now.to_i)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Refreshes the current Access Token
|
81
|
-
#
|
82
|
-
# @return [AccessToken] a new AccessToken
|
83
|
-
# @note options should be carried over to the new AccessToken
|
84
|
-
def refresh!(params = {})
|
85
|
-
fail('A refresh_token is not available') unless refresh_token
|
86
|
-
params.merge!(:client_id => @client.id,
|
87
|
-
:client_secret => @client.secret,
|
88
|
-
:grant_type => 'refresh_token',
|
89
|
-
:refresh_token => refresh_token)
|
90
|
-
new_token = @client.get_token(params)
|
91
|
-
new_token.options = options
|
92
|
-
new_token.refresh_token = refresh_token unless new_token.refresh_token
|
93
|
-
new_token
|
94
|
-
end
|
95
|
-
|
96
|
-
# Convert AccessToken to a hash which can be used to rebuild itself with AccessToken.from_hash
|
97
|
-
#
|
98
|
-
# @return [Hash] a hash of AccessToken property values
|
99
|
-
def to_hash
|
100
|
-
params.merge(:access_token => token, :refresh_token => refresh_token, :expires_at => expires_at)
|
101
|
-
end
|
102
|
-
|
103
|
-
# Make a request with the Access Token
|
104
|
-
#
|
105
|
-
# @param [Symbol] verb the HTTP request method
|
106
|
-
# @param [String] path the HTTP URL path of the request
|
107
|
-
# @param [Hash] opts the options to make the request with
|
108
|
-
# @see Client#request
|
109
|
-
def request(verb, path, opts = {}, &block)
|
110
|
-
self.token = opts
|
111
|
-
@client.request(verb, path, opts, &block)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Make a GET request with the Access Token
|
115
|
-
#
|
116
|
-
# @see AccessToken#request
|
117
|
-
def get(path, opts = {}, &block)
|
118
|
-
request(:get, path, opts, &block)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Make a POST request with the Access Token
|
122
|
-
#
|
123
|
-
# @see AccessToken#request
|
124
|
-
def post(path, opts = {}, &block)
|
125
|
-
request(:post, path, opts, &block)
|
126
|
-
end
|
127
|
-
|
128
|
-
# Make a PUT request with the Access Token
|
129
|
-
#
|
130
|
-
# @see AccessToken#request
|
131
|
-
def put(path, opts = {}, &block)
|
132
|
-
request(:put, path, opts, &block)
|
133
|
-
end
|
134
|
-
|
135
|
-
# Make a PATCH request with the Access Token
|
136
|
-
#
|
137
|
-
# @see AccessToken#request
|
138
|
-
def patch(path, opts = {}, &block)
|
139
|
-
request(:patch, path, opts, &block)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Make a DELETE request with the Access Token
|
143
|
-
#
|
144
|
-
# @see AccessToken#request
|
145
|
-
def delete(path, opts = {}, &block)
|
146
|
-
request(:delete, path, opts, &block)
|
147
|
-
end
|
148
|
-
|
149
|
-
# Get the headers hash (includes Authorization token)
|
150
|
-
def headers
|
151
|
-
{'Authorization' => options[:header_format] % token}
|
152
|
-
end
|
153
|
-
|
154
|
-
private
|
155
|
-
|
156
|
-
def token=(opts) # rubocop:disable MethodLength
|
157
|
-
case options[:mode]
|
158
|
-
when :header
|
159
|
-
opts[:headers] ||= {}
|
160
|
-
opts[:headers].merge!(headers)
|
161
|
-
when :query
|
162
|
-
opts[:params] ||= {}
|
163
|
-
opts[:params][options[:param_name]] = token
|
164
|
-
when :body
|
165
|
-
opts[:body] ||= {}
|
166
|
-
if opts[:body].is_a?(Hash)
|
167
|
-
opts[:body][options[:param_name]] = token
|
168
|
-
else
|
169
|
-
opts[:body] << "&#{options[:param_name]}=#{token}"
|
170
|
-
end
|
171
|
-
# @todo support for multi-part (file uploads)
|
172
|
-
else
|
173
|
-
fail("invalid :mode option of #{options[:mode]}")
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
data/lib/base.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module OAuth2
|
2
|
-
module Strategy
|
3
|
-
class Base
|
4
|
-
def initialize(client)
|
5
|
-
@client = client
|
6
|
-
end
|
7
|
-
|
8
|
-
# The OAuth client_id and client_secret
|
9
|
-
#
|
10
|
-
# @return [Hash]
|
11
|
-
def client_params
|
12
|
-
{'client_id' => @client.id, 'client_secret' => @client.secret}
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/lib/client.rb
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'logger'
|
3
|
-
require 'access_token'
|
4
|
-
|
5
|
-
module OAuth2
|
6
|
-
# The OAuth2::Client class
|
7
|
-
class Client
|
8
|
-
attr_reader :id, :secret, :site
|
9
|
-
attr_accessor :options
|
10
|
-
attr_writer :connection
|
11
|
-
|
12
|
-
# Instantiate a new OAuth 2.0 client using the
|
13
|
-
# Client ID and Client Secret registered to your
|
14
|
-
# application.
|
15
|
-
#
|
16
|
-
# @param [String] client_id the client_id value
|
17
|
-
# @param [String] client_secret the client_secret value
|
18
|
-
# @param [Hash] opts the options to create the client with
|
19
|
-
# @option opts [String] :site the OAuth2 provider site host
|
20
|
-
# @option opts [String] :authorize_url ('/oauth/authorize') absolute or relative URL path to the Authorization endpoint
|
21
|
-
# @option opts [String] :token_url ('/oauth/token') absolute or relative URL path to the Token endpoint
|
22
|
-
# @option opts [Symbol] :token_method (:post) HTTP method to use to request token (:get or :post)
|
23
|
-
# @option opts [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday with
|
24
|
-
# @option opts [FixNum] :max_redirects (5) maximum number of redirects to follow
|
25
|
-
# @option opts [Boolean] :raise_errors (true) whether or not to raise an OAuth2::Error
|
26
|
-
# on responses with 400+ status codes
|
27
|
-
# @yield [builder] The Faraday connection builder
|
28
|
-
def initialize(client_id, client_secret, options = {}, &block)
|
29
|
-
opts = options.dup
|
30
|
-
@id = client_id
|
31
|
-
@secret = client_secret
|
32
|
-
@site = opts.delete(:site)
|
33
|
-
ssl = opts.delete(:ssl)
|
34
|
-
@options = {:authorize_url => '/oauth/authorize',
|
35
|
-
:token_url => '/oauth/token',
|
36
|
-
:token_method => :post,
|
37
|
-
:connection_opts => {},
|
38
|
-
:connection_build => block,
|
39
|
-
:max_redirects => 5,
|
40
|
-
:raise_errors => true}.merge(opts)
|
41
|
-
@options[:connection_opts][:ssl] = ssl if ssl
|
42
|
-
end
|
43
|
-
|
44
|
-
# Set the site host
|
45
|
-
#
|
46
|
-
# @param [String] the OAuth2 provider site host
|
47
|
-
def site=(value)
|
48
|
-
@connection = nil
|
49
|
-
@site = value
|
50
|
-
end
|
51
|
-
|
52
|
-
# The Faraday connection object
|
53
|
-
def connection
|
54
|
-
@connection ||= begin
|
55
|
-
conn = Faraday.new(site, options[:connection_opts])
|
56
|
-
conn.build do |b|
|
57
|
-
options[:connection_build].call(b)
|
58
|
-
end if options[:connection_build]
|
59
|
-
conn
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# The authorize endpoint URL of the OAuth2 provider
|
64
|
-
#
|
65
|
-
# @param [Hash] params additional query parameters
|
66
|
-
def authorize_url(params = nil)
|
67
|
-
connection.build_url(options[:authorize_url], params).to_s
|
68
|
-
end
|
69
|
-
|
70
|
-
# The token endpoint URL of the OAuth2 provider
|
71
|
-
#
|
72
|
-
# @param [Hash] params additional query parameters
|
73
|
-
def token_url(params = nil)
|
74
|
-
connection.build_url(options[:token_url], params).to_s
|
75
|
-
end
|
76
|
-
|
77
|
-
# Makes a request relative to the specified site root.
|
78
|
-
#
|
79
|
-
# @param [Symbol] verb one of :get, :post, :put, :delete
|
80
|
-
# @param [String] url URL path of request
|
81
|
-
# @param [Hash] opts the options to make the request with
|
82
|
-
# @option opts [Hash] :params additional query parameters for the URL of the request
|
83
|
-
# @option opts [Hash, String] :body the body of the request
|
84
|
-
# @option opts [Hash] :headers http request headers
|
85
|
-
# @option opts [Boolean] :raise_errors whether or not to raise an OAuth2::Error on 400+ status
|
86
|
-
# code response for this request. Will default to client option
|
87
|
-
# @option opts [Symbol] :parse @see Response::initialize
|
88
|
-
# @yield [req] The Faraday request
|
89
|
-
def request(verb, url, opts = {}) # rubocop:disable CyclomaticComplexity, MethodLength
|
90
|
-
connection.response :logger, ::Logger.new($stdout) if ENV['OAUTH_DEBUG'] == 'true'
|
91
|
-
|
92
|
-
url = connection.build_url(url, opts[:params]).to_s
|
93
|
-
|
94
|
-
response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req|
|
95
|
-
yield(req) if block_given?
|
96
|
-
end
|
97
|
-
response = Response.new(response, :parse => opts[:parse])
|
98
|
-
|
99
|
-
case response.status
|
100
|
-
when 301, 302, 303, 307
|
101
|
-
opts[:redirect_count] ||= 0
|
102
|
-
opts[:redirect_count] += 1
|
103
|
-
return response if opts[:redirect_count] > options[:max_redirects]
|
104
|
-
if response.status == 303
|
105
|
-
verb = :get
|
106
|
-
opts.delete(:body)
|
107
|
-
end
|
108
|
-
request(verb, response.headers['location'], opts)
|
109
|
-
when 200..299, 300..399
|
110
|
-
# on non-redirecting 3xx statuses, just return the response
|
111
|
-
response
|
112
|
-
when 400..599
|
113
|
-
error = Error.new(response)
|
114
|
-
fail(error) if opts.fetch(:raise_errors, options[:raise_errors])
|
115
|
-
response.error = error
|
116
|
-
response
|
117
|
-
else
|
118
|
-
error = Error.new(response)
|
119
|
-
fail(error, "Unhandled status code value of #{response.status}")
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# Initializes an AccessToken by making a request to the token endpoint
|
124
|
-
#
|
125
|
-
# @param [Hash] params a Hash of params for the token endpoint
|
126
|
-
# @param [Hash] access token options, to pass to the AccessToken object
|
127
|
-
# @param [Class] class of access token for easier subclassing OAuth2::AccessToken
|
128
|
-
# @return [AccessToken] the initalized AccessToken
|
129
|
-
def get_token(params, access_token_opts = {})
|
130
|
-
opts = {:raise_errors => options[:raise_errors], :parse => params.delete(:parse)}
|
131
|
-
if options[:token_method] == :post
|
132
|
-
headers = params.delete(:headers)
|
133
|
-
opts[:body] = params
|
134
|
-
opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
|
135
|
-
opts[:headers].merge!(headers) if headers
|
136
|
-
else
|
137
|
-
opts[:params] = params
|
138
|
-
end
|
139
|
-
response = request(options[:token_method], token_url, opts)
|
140
|
-
error = Error.new(response)
|
141
|
-
fail(error) if options[:raise_errors] && !(response.parsed.is_a?(Hash) && response.parsed['access_token'])
|
142
|
-
hash = response.parsed.merge(access_token_opts)
|
143
|
-
AccessToken.new(self, hash.delete('access_token') || hash.delete(:access_token), hash)
|
144
|
-
#AccessToken.from_hash(self, response.parsed.merge(access_token_opts))
|
145
|
-
#access_token_class.from_hash(self, response.parsed.merge(access_token_opts))
|
146
|
-
end
|
147
|
-
|
148
|
-
# The Client Credentials strategy
|
149
|
-
#
|
150
|
-
# @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
|
151
|
-
def client_credentials
|
152
|
-
@client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
data/lib/client_credentials.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'base64'
|
2
|
-
|
3
|
-
module OAuth2
|
4
|
-
module Strategy
|
5
|
-
# The Client Credentials Strategy
|
6
|
-
#
|
7
|
-
# @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
|
8
|
-
class ClientCredentials < Base
|
9
|
-
# Not used for this strategy
|
10
|
-
#
|
11
|
-
# @raise [NotImplementedError]
|
12
|
-
def authorize_url
|
13
|
-
fail(NotImplementedError, 'The authorization endpoint is not used in this strategy')
|
14
|
-
end
|
15
|
-
|
16
|
-
# Retrieve an access token given the specified client.
|
17
|
-
#
|
18
|
-
# @param [Hash] params additional params
|
19
|
-
# @param [Hash] opts options
|
20
|
-
def get_token(params = {}, opts = {})
|
21
|
-
request_body = opts.delete('auth_scheme') == 'request_body'
|
22
|
-
params.merge!('grant_type' => 'client_credentials')
|
23
|
-
params.merge!(request_body ? client_params : {:headers => {'Authorization' => authorization(client_params['client_id'], client_params['client_secret'])}})
|
24
|
-
@client.get_token(params, opts.merge('refresh_token' => nil))
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns the Authorization header value for Basic Authentication
|
28
|
-
#
|
29
|
-
# @param [String] The client ID
|
30
|
-
# @param [String] the client secret
|
31
|
-
def authorization(client_id, client_secret)
|
32
|
-
'Basic ' + Base64.encode64(client_id + ':' + client_secret).gsub("\n", '')
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
data/lib/error.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module OAuth2
|
2
|
-
class Error < StandardError
|
3
|
-
attr_reader :response, :code, :description
|
4
|
-
|
5
|
-
# standard error values include:
|
6
|
-
# :invalid_request, :invalid_client, :invalid_token, :invalid_grant, :unsupported_grant_type, :invalid_scope
|
7
|
-
def initialize(response)
|
8
|
-
response.error = self
|
9
|
-
@response = response
|
10
|
-
|
11
|
-
message = []
|
12
|
-
|
13
|
-
if response.parsed.is_a?(Hash)
|
14
|
-
@code = response.parsed['error']
|
15
|
-
@description = response.parsed['error_description']
|
16
|
-
message << "#{@code}: #{@description}"
|
17
|
-
end
|
18
|
-
|
19
|
-
message << response.body
|
20
|
-
|
21
|
-
super(message.join("\n"))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/response.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
module OAuth2
|
2
|
-
# OAuth2::Response class
|
3
|
-
class Response
|
4
|
-
attr_reader :response
|
5
|
-
attr_accessor :error, :options
|
6
|
-
|
7
|
-
# Adds a new content type parser.
|
8
|
-
#
|
9
|
-
# @param [Symbol] key A descriptive symbol key such as :json or :query.
|
10
|
-
# @param [Array] One or more mime types to which this parser applies.
|
11
|
-
# @yield [String] A block returning parsed content.
|
12
|
-
def self.register_parser(key, mime_types, &block)
|
13
|
-
key = key.to_sym
|
14
|
-
PARSERS[key] = block
|
15
|
-
Array(mime_types).each do |mime_type|
|
16
|
-
CONTENT_TYPES[mime_type] = key
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Initializes a Response instance
|
21
|
-
#
|
22
|
-
# @param [Faraday::Response] response The Faraday response instance
|
23
|
-
# @param [Hash] opts options in which to initialize the instance
|
24
|
-
# @option opts [Symbol] :parse (:automatic) how to parse the response body. one of :query (for x-www-form-urlencoded),
|
25
|
-
# :json, or :automatic (determined by Content-Type response header)
|
26
|
-
def initialize(response, opts = {})
|
27
|
-
@response = response
|
28
|
-
@options = {:parse => :automatic}.merge(opts)
|
29
|
-
end
|
30
|
-
|
31
|
-
# The HTTP response headers
|
32
|
-
def headers
|
33
|
-
response.headers
|
34
|
-
end
|
35
|
-
|
36
|
-
# The HTTP response status code
|
37
|
-
def status
|
38
|
-
response.status
|
39
|
-
end
|
40
|
-
|
41
|
-
# The HTTP response body
|
42
|
-
def body
|
43
|
-
response.body || ''
|
44
|
-
end
|
45
|
-
|
46
|
-
# Procs that, when called, will parse a response body according
|
47
|
-
# to the specified format.
|
48
|
-
PARSERS = {
|
49
|
-
:json => lambda { |body| JSON.parse(body) rescue body }, # rubocop:disable RescueModifier
|
50
|
-
#:query => lambda { |body| Rack::Utils.parse_query(body) },
|
51
|
-
:text => lambda { |body| body }
|
52
|
-
}
|
53
|
-
|
54
|
-
# Content type assignments for various potential HTTP content types.
|
55
|
-
CONTENT_TYPES = {
|
56
|
-
'application/json' => :json,
|
57
|
-
'text/javascript' => :json,
|
58
|
-
'application/x-www-form-urlencoded' => :query,
|
59
|
-
'text/plain' => :text
|
60
|
-
}
|
61
|
-
|
62
|
-
# The parsed response body.
|
63
|
-
# Will attempt to parse application/x-www-form-urlencoded and
|
64
|
-
# application/json Content-Type response bodies
|
65
|
-
def parsed
|
66
|
-
return nil unless PARSERS.key?(parser)
|
67
|
-
@parsed ||= PARSERS[parser].call(body)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Attempts to determine the content type of the response.
|
71
|
-
def content_type
|
72
|
-
((response.headers.values_at('content-type', 'Content-Type').compact.first || '').split(';').first || '').strip
|
73
|
-
end
|
74
|
-
|
75
|
-
# Determines the parser that will be used to supply the content of #parsed
|
76
|
-
def parser
|
77
|
-
return options[:parse].to_sym if PARSERS.key?(options[:parse])
|
78
|
-
CONTENT_TYPES[content_type]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
data/lib/strategy.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'jwt'
|
2
|
-
|
3
|
-
module OAuth2
|
4
|
-
module Strategy
|
5
|
-
# The Client Assertion Strategy
|
6
|
-
#
|
7
|
-
# @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.3
|
8
|
-
#
|
9
|
-
# Sample usage:
|
10
|
-
# client = OAuth2::Client.new(client_id, client_secret,
|
11
|
-
# :site => 'http://localhost:8080')
|
12
|
-
#
|
13
|
-
# params = {:hmac_secret => "some secret",
|
14
|
-
# # or :private_key => "private key string",
|
15
|
-
# :iss => "http://localhost:3001",
|
16
|
-
# :prn => "me@here.com",
|
17
|
-
# :exp => Time.now.utc.to_i + 3600}
|
18
|
-
#
|
19
|
-
# access = client.assertion.get_token(params)
|
20
|
-
# access.token # actual access_token string
|
21
|
-
# access.get("/api/stuff") # making api calls with access token in header
|
22
|
-
#
|
23
|
-
class Assertion < Base
|
24
|
-
# Not used for this strategy
|
25
|
-
#
|
26
|
-
# @raise [NotImplementedError]
|
27
|
-
def authorize_url
|
28
|
-
fail(NotImplementedError, 'The authorization endpoint is not used in this strategy')
|
29
|
-
end
|
30
|
-
|
31
|
-
# Retrieve an access token given the specified client.
|
32
|
-
#
|
33
|
-
# @param [Hash] params assertion params
|
34
|
-
# pass either :hmac_secret or :private_key, but not both.
|
35
|
-
#
|
36
|
-
# params :hmac_secret, secret string.
|
37
|
-
# params :private_key, private key string.
|
38
|
-
#
|
39
|
-
# params :iss, issuer
|
40
|
-
# params :aud, audience, optional
|
41
|
-
# params :prn, principal, current user
|
42
|
-
# params :exp, expired at, in seconds, like Time.now.utc.to_i + 3600
|
43
|
-
#
|
44
|
-
# @param [Hash] opts options
|
45
|
-
def get_token(params = {}, opts = {})
|
46
|
-
hash = build_request(params)
|
47
|
-
@client.get_token(hash, opts.merge('refresh_token' => nil))
|
48
|
-
end
|
49
|
-
|
50
|
-
def build_request(params)
|
51
|
-
assertion = build_assertion(params)
|
52
|
-
{:grant_type => 'assertion',
|
53
|
-
:assertion_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
54
|
-
:assertion => assertion,
|
55
|
-
:scope => params[:scope]
|
56
|
-
}.merge(client_params)
|
57
|
-
end
|
58
|
-
|
59
|
-
def build_assertion(params)
|
60
|
-
claims = {:iss => params[:iss],
|
61
|
-
:aud => params[:aud],
|
62
|
-
:prn => params[:prn],
|
63
|
-
:exp => params[:exp]
|
64
|
-
}
|
65
|
-
if params[:hmac_secret]
|
66
|
-
JWT.encode(claims, params[:hmac_secret], 'HS256')
|
67
|
-
elsif params[:private_key]
|
68
|
-
JWT.encode(claims, params[:private_key], 'RS256')
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|