/
access_token.rb
175 lines (158 loc) · 5.87 KB
/
access_token.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
module OAuth2
class AccessToken
attr_reader :client, :token, :expires_in, :expires_at, :params
attr_accessor :options, :refresh_token
class << self
# Initializes an AccessToken from a Hash
#
# @param [Client] the OAuth2::Client instance
# @param [Hash] a hash of AccessToken property values
# @return [AccessToken] the initalized AccessToken
def from_hash(client, hash)
hash = hash.dup
new(client, hash.delete('access_token') || hash.delete(:access_token), hash)
end
# Initializes an AccessToken from a key/value application/x-www-form-urlencoded string
#
# @param [Client] client the OAuth2::Client instance
# @param [String] kvform the application/x-www-form-urlencoded string
# @return [AccessToken] the initalized AccessToken
def from_kvform(client, kvform)
from_hash(client, Rack::Utils.parse_query(kvform))
end
end
# Initalize an AccessToken
#
# @param [Client] client the OAuth2::Client instance
# @param [String] token the Access Token value
# @param [Hash] opts the options to create the Access Token with
# @option opts [String] :refresh_token (nil) the refresh_token value
# @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire
# @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire
# @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value
# one of :header, :body or :query
# @option opts [String] :header_format ('Bearer %s') the string format to use for the Authorization header
# @option opts [String] :param_name ('access_token') the parameter name to use for transmission of the
# Access Token value in :body or :query transmission mode
def initialize(client, token, opts = {}) # rubocop:disable Metrics/AbcSize
@client = client
@token = token.to_s
opts = opts.dup
[:refresh_token, :expires_in, :expires_at].each do |arg|
instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s))
end
@expires_in ||= opts.delete('expires')
@expires_in &&= @expires_in.to_i
@expires_at &&= @expires_at.to_i
@expires_at ||= Time.now.to_i + @expires_in if @expires_in
@options = {:mode => opts.delete(:mode) || :header,
:header_format => opts.delete(:header_format) || 'Bearer %s',
:param_name => opts.delete(:param_name) || 'access_token'}
@params = opts
end
# Indexer to additional params present in token response
#
# @param [String] key entry key to Hash
def [](key)
@params[key]
end
# Whether or not the token expires
#
# @return [Boolean]
def expires?
!!@expires_at
end
# Whether or not the token is expired
#
# @return [Boolean]
def expired?
expires? && (expires_at < Time.now.to_i)
end
# Refreshes the current Access Token
#
# @return [AccessToken] a new AccessToken
# @note options should be carried over to the new AccessToken
def refresh!(params = {})
raise('A refresh_token is not available') unless refresh_token
params[:client_id] = @client.id
params[:client_secret] = @client.secret
params[:grant_type] = 'refresh_token'
params[:refresh_token] = refresh_token
new_token = @client.get_token(params)
new_token.options = options
new_token.refresh_token = refresh_token unless new_token.refresh_token
new_token
end
# Convert AccessToken to a hash which can be used to rebuild itself with AccessToken.from_hash
#
# @return [Hash] a hash of AccessToken property values
def to_hash
params.merge(:access_token => token, :refresh_token => refresh_token, :expires_at => expires_at)
end
# Make a request with the Access Token
#
# @param [Symbol] verb the HTTP request method
# @param [String] path the HTTP URL path of the request
# @param [Hash] opts the options to make the request with
# @see Client#request
def request(verb, path, opts = {}, &block)
self.token = opts
@client.request(verb, path, opts, &block)
end
# Make a GET request with the Access Token
#
# @see AccessToken#request
def get(path, opts = {}, &block)
request(:get, path, opts, &block)
end
# Make a POST request with the Access Token
#
# @see AccessToken#request
def post(path, opts = {}, &block)
request(:post, path, opts, &block)
end
# Make a PUT request with the Access Token
#
# @see AccessToken#request
def put(path, opts = {}, &block)
request(:put, path, opts, &block)
end
# Make a PATCH request with the Access Token
#
# @see AccessToken#request
def patch(path, opts = {}, &block)
request(:patch, path, opts, &block)
end
# Make a DELETE request with the Access Token
#
# @see AccessToken#request
def delete(path, opts = {}, &block)
request(:delete, path, opts, &block)
end
# Get the headers hash (includes Authorization token)
def headers
{'Authorization' => options[:header_format] % token}
end
private
def token=(opts) # rubocop:disable MethodLength, Metrics/AbcSize
case options[:mode]
when :header
opts[:headers] ||= {}
opts[:headers].merge!(headers)
when :query
opts[:params] ||= {}
opts[:params][options[:param_name]] = token
when :body
opts[:body] ||= {}
if opts[:body].is_a?(Hash)
opts[:body][options[:param_name]] = token
else
opts[:body] << "&#{options[:param_name]}=#{token}"
end
# @todo support for multi-part (file uploads)
else
raise("invalid :mode option of #{options[:mode]}")
end
end
end
end