ginjo-omniauth-slack 2.4.1 → 2.5.0
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 +4 -4
- data/.gitignore +6 -5
- data/.rdoc_options +33 -0
- data/.yardopts +14 -0
- data/CHANGELOG.md +18 -1
- data/Gemfile +5 -1
- data/README.md +498 -169
- data/Rakefile +1 -0
- data/lib/omniauth-slack/debug.rb +57 -0
- data/lib/omniauth-slack/oauth2/access_token.rb +382 -0
- data/lib/omniauth-slack/oauth2/client.rb +95 -0
- data/lib/omniauth-slack/omniauth/auth_hash.rb +10 -0
- data/lib/omniauth-slack/refinements.rb +68 -0
- data/lib/omniauth-slack/slack.rb +121 -0
- data/lib/omniauth-slack/version.rb +1 -1
- data/lib/omniauth/strategies/slack.rb +212 -343
- data/test/access_token_test.rb +123 -0
- data/test/helper.rb +40 -5
- data/test/refinements_test.rb +83 -0
- data/test/strategy_test.rb +249 -0
- data/test/support/oauth_user_token_response_v2.json +16 -0
- data/test/support/scope_base.yml +25 -0
- data/test/support/shared_examples.rb +0 -10
- data/test/test.rb +1 -249
- metadata +20 -2
data/Rakefile
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'omniauth-slack/refinements'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
# Appends 'TRACE' option to Logger levels.
|
5
|
+
sev_label_new = Logger::SEV_LABEL.dup
|
6
|
+
sev_label_new << 'TRACE'
|
7
|
+
Logger::Severity::TRACE = (sev_label_new.size - 1)
|
8
|
+
Logger.send(:remove_const, :SEV_LABEL)
|
9
|
+
Logger::SEV_LABEL = sev_label_new.freeze
|
10
|
+
|
11
|
+
module OmniAuth
|
12
|
+
module Slack
|
13
|
+
module Debug
|
14
|
+
#using ObjectRefinements
|
15
|
+
LOG_ALL = %w(1 true yes all debug)
|
16
|
+
LOG_NONE = %w(0 false no none nil nill null)
|
17
|
+
|
18
|
+
include CallerMethodName
|
19
|
+
|
20
|
+
def self.included(other)
|
21
|
+
other.send(:include, CallerMethodName)
|
22
|
+
other.send(:extend, Extensions)
|
23
|
+
end
|
24
|
+
|
25
|
+
module Extensions
|
26
|
+
def debug(method_name = nil, klass=nil, &block)
|
27
|
+
method_name ||= caller_method_name
|
28
|
+
klass ||= self
|
29
|
+
filter = ENV['OMNIAUTH_SLACK_DEBUG']
|
30
|
+
return if filter.nil? || filter.to_s=='' || LOG_NONE.include?(filter.to_s.downcase)
|
31
|
+
klass = case klass
|
32
|
+
when Class; klass.name
|
33
|
+
when Module; klass.name
|
34
|
+
when String; klass
|
35
|
+
else klass.to_s
|
36
|
+
end
|
37
|
+
klass_name = klass.to_s.split('::').last.to_s
|
38
|
+
log_text = yield
|
39
|
+
full_text = "(#{klass_name} #{method_name}) #{log_text}" #{Thread.current.object_id}
|
40
|
+
|
41
|
+
if filter && !LOG_ALL.include?(filter.to_s.downcase)
|
42
|
+
regexp = filter.is_a?(Regexp) ? filter : Regexp.new(filter.to_s, true)
|
43
|
+
return unless full_text[regexp]
|
44
|
+
end
|
45
|
+
|
46
|
+
OmniAuth.logger.log(Logger::TRACE, full_text)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def debug(method_name=nil, klass=nil, &block)
|
51
|
+
method_name ||= caller_method_name
|
52
|
+
self.class.debug(method_name, klass, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,382 @@
|
|
1
|
+
# :markup: tomdoc
|
2
|
+
|
3
|
+
require 'oauth2/access_token'
|
4
|
+
require 'omniauth-slack/refinements'
|
5
|
+
require 'omniauth-slack/debug'
|
6
|
+
|
7
|
+
module OmniAuth
|
8
|
+
module Slack
|
9
|
+
using StringRefinements
|
10
|
+
using OAuth2Refinements
|
11
|
+
|
12
|
+
module OAuth2
|
13
|
+
|
14
|
+
# This is an enhanced subclass of OAuth2::AccessToken.
|
15
|
+
# It handles Slack-specific data and behavior, and it also adds
|
16
|
+
# a scope-query method has_scope?
|
17
|
+
#
|
18
|
+
# The AccessToken object is built with the hash returned from the get-token API request
|
19
|
+
# or is passed in manually via AccessToken.from_hash() or OmniAuth::Slack::build_access_token.
|
20
|
+
#
|
21
|
+
# The original hash from the API can always be found at AccessToken#params.
|
22
|
+
# As a convenience, you can call '[]' on the params hash by sending
|
23
|
+
# the method and args directly to the access-token object.
|
24
|
+
#
|
25
|
+
# my_token['ok'] --> true
|
26
|
+
# my_token['app_id'] --> A012345678
|
27
|
+
#
|
28
|
+
# The AccessToken instance provides getter methods for top-level data points
|
29
|
+
# of the returned token hash. See define_getters call below for more convenience methods.
|
30
|
+
#
|
31
|
+
# See Slack's documentation for the different types of tokens available.
|
32
|
+
#
|
33
|
+
# * https://api.slack.com/methods/oauth.access
|
34
|
+
# * https://api.slack.com/methods/oauth.v2.access
|
35
|
+
#
|
36
|
+
class AccessToken < ::OAuth2::AccessToken
|
37
|
+
include OmniAuth::Slack::Debug
|
38
|
+
|
39
|
+
# Creates simple getter methods to pull specific data from the raw token hash.
|
40
|
+
def self.define_getters(ary_of_words)
|
41
|
+
ary_of_words.each do |word|
|
42
|
+
obj, atrb = word.split('_')
|
43
|
+
define_method(word) do
|
44
|
+
rslt = (
|
45
|
+
params[word] ||
|
46
|
+
params && params[obj] && params[obj][atrb]
|
47
|
+
)
|
48
|
+
debug { "Simple getter '#{word}' rslt: #{rslt}" }
|
49
|
+
rslt
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
define_getters %w(
|
55
|
+
app_id
|
56
|
+
authorizing_user
|
57
|
+
enterprise
|
58
|
+
installer_user
|
59
|
+
scope
|
60
|
+
team
|
61
|
+
team_id
|
62
|
+
team_name
|
63
|
+
team_domain
|
64
|
+
user
|
65
|
+
)
|
66
|
+
|
67
|
+
# Check's the token hash 'ok' field.
|
68
|
+
#
|
69
|
+
# Returns true or false, representing the success status of the token response.
|
70
|
+
#
|
71
|
+
def ok?
|
72
|
+
params['ok'] == true ||
|
73
|
+
params['ok'].to_s[/true/i] ||
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
# Intercepts super to return nil instead of an empty string.
|
78
|
+
#
|
79
|
+
# Returns the token string or nil.
|
80
|
+
#
|
81
|
+
def token
|
82
|
+
rslt = super
|
83
|
+
rslt.to_s == '' ? nil : rslt
|
84
|
+
end
|
85
|
+
|
86
|
+
# Inspects the token and determines token type.
|
87
|
+
#
|
88
|
+
# Returns a string representing token type.
|
89
|
+
#
|
90
|
+
def token_type
|
91
|
+
params['token_type'] ||
|
92
|
+
case
|
93
|
+
when
|
94
|
+
params['token_type'] == 'user' ||
|
95
|
+
@token.to_s[/xoxp/]; 'user'
|
96
|
+
when
|
97
|
+
params['token_type'] == 'bot' ||
|
98
|
+
@token.to_s[/xoxb/]; 'bot'
|
99
|
+
when
|
100
|
+
params['token_type'] == 'app' ||
|
101
|
+
@token.to_s[/xoxa/]; 'app'
|
102
|
+
when
|
103
|
+
@token.to_s[/xoxr/]; 'refresh'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Compares given token type with actual token_type.
|
108
|
+
#
|
109
|
+
# Returns true if given type matches actual token_type, otherwise false.
|
110
|
+
#
|
111
|
+
def token_type?(*_type)
|
112
|
+
#debug{"'#{_type}'"}
|
113
|
+
[_type].flatten.any? do |t|
|
114
|
+
token_type.to_s == t.to_s
|
115
|
+
end || false
|
116
|
+
end
|
117
|
+
|
118
|
+
# Converts 'authed_user' hash (of Slack v2 oauth flow) to AccessToken object.
|
119
|
+
#
|
120
|
+
# Returns an AccessToken instance or nil.
|
121
|
+
#
|
122
|
+
def user_token
|
123
|
+
@user_token ||= (
|
124
|
+
if token_type?('user')
|
125
|
+
self
|
126
|
+
elsif params['authed_user']
|
127
|
+
rslt = self.class.from_hash(client, params['authed_user']).tap do |t|
|
128
|
+
t.params['token_type'] = 'user'
|
129
|
+
t.params['team_id'] = team_id
|
130
|
+
end
|
131
|
+
end
|
132
|
+
)
|
133
|
+
end
|
134
|
+
alias_method :authed_user, :user_token
|
135
|
+
|
136
|
+
# Gets the AccessToken person-user-id if it exists.
|
137
|
+
#
|
138
|
+
# Returns string or nil.
|
139
|
+
#
|
140
|
+
def user_id
|
141
|
+
rslt = (
|
142
|
+
# classic token.
|
143
|
+
params['user_id'] ||
|
144
|
+
# from sub-token in 'authed_user'
|
145
|
+
params['authed_user'].to_h['id'] ||
|
146
|
+
# workspace-app token with attached user.
|
147
|
+
params['user'].to_h['id'] ||
|
148
|
+
# workspace-app token with authorizing user.
|
149
|
+
params['authorizing_user'].to_h['user_id'] ||
|
150
|
+
# workspace-app token with installer user.
|
151
|
+
params['installer_user'].to_h['user_id'] ||
|
152
|
+
# user-id from authed_user hash.
|
153
|
+
params['id'] #||
|
154
|
+
# v2 api bot token, as a last resort.
|
155
|
+
#params['bot_user_id']
|
156
|
+
)
|
157
|
+
debug { rslt }
|
158
|
+
rslt
|
159
|
+
end
|
160
|
+
|
161
|
+
# Gets the AccessToken unique user-team-id combo, if it can be determined.
|
162
|
+
#
|
163
|
+
# Returns string or nil.
|
164
|
+
#
|
165
|
+
def uid
|
166
|
+
rslt = (user_id && team_id) ? "#{user_id}-#{team_id}" : nil
|
167
|
+
debug { rslt }
|
168
|
+
rslt
|
169
|
+
end
|
170
|
+
|
171
|
+
# Gets user_name from wherever it can be found in the returned token,
|
172
|
+
# regardless of what type of token is returned.
|
173
|
+
#
|
174
|
+
# Returns string or nil.
|
175
|
+
#
|
176
|
+
def user_name
|
177
|
+
params['user_name'] ||
|
178
|
+
# from sub-token in 'authed_user'
|
179
|
+
params['authed_user'].to_h['name'] ||
|
180
|
+
# workspace-app token with attached user.
|
181
|
+
params['user'].to_h['name'] ||
|
182
|
+
# from authed_user hash.
|
183
|
+
params['name'] ||
|
184
|
+
# workspace token with authorizing user.
|
185
|
+
params['authorizing_user'].to_h['name'] ||
|
186
|
+
# workspace token with installer user.
|
187
|
+
params['installer_user'].to_h['name'] ||
|
188
|
+
# more workspace token possibilities.
|
189
|
+
to_auth_hash.deep_find('nickname') ||
|
190
|
+
to_auth_hash.deep_find('real_name')
|
191
|
+
end
|
192
|
+
|
193
|
+
# Gets bot_user_id if it exists.
|
194
|
+
#
|
195
|
+
# Returns string or nil.
|
196
|
+
#
|
197
|
+
def bot_user_id
|
198
|
+
params['bot_user_id']
|
199
|
+
end
|
200
|
+
|
201
|
+
# Gets the app_user_id if it exists.
|
202
|
+
#
|
203
|
+
# Returns string or nil.
|
204
|
+
#
|
205
|
+
def app_user_id
|
206
|
+
params['app_user_id']
|
207
|
+
end
|
208
|
+
|
209
|
+
# Experimental, converts this AccessToken instance to an AuthHash object.
|
210
|
+
#
|
211
|
+
# Returns OmniAuth::Slack::AuthHash instance.
|
212
|
+
#
|
213
|
+
def to_auth_hash
|
214
|
+
Module.const_get('::OmniAuth::Slack::AuthHash').new(params)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Compiles scopes awarded to this AccessToken.
|
218
|
+
#
|
219
|
+
# Returns hash of scope arrays where *key* is scope section
|
220
|
+
# and *value* is Array of scopes.
|
221
|
+
#
|
222
|
+
def all_scopes
|
223
|
+
@all_scopes ||= (
|
224
|
+
case
|
225
|
+
when ! params['scope'].to_s.empty?
|
226
|
+
{'classic' => params['scope'].words}
|
227
|
+
when params['scopes'].to_h.any?
|
228
|
+
params['scopes']
|
229
|
+
end
|
230
|
+
)
|
231
|
+
end
|
232
|
+
alias_method :scopes, :all_scopes
|
233
|
+
|
234
|
+
# Match a given set of scopes against this token's awarded scopes,
|
235
|
+
# classic and workspace token compatible.
|
236
|
+
#
|
237
|
+
# If the scope-query is a string, it will be interpreted as a Slack Classic App
|
238
|
+
# scope string {classic: scope-query-string}, even if the token is a v2 token.
|
239
|
+
#
|
240
|
+
# The keywords need to be symbols, so any hash passed as an argument
|
241
|
+
# (or as the entire set of args) should have symbolized keys!
|
242
|
+
#
|
243
|
+
# freeform_array - [*Array, nil] default: [], array of scope query hashes or string(s).
|
244
|
+
#
|
245
|
+
# :query - [Hash, Array, nil] default: nil, a single scope-query Hash (or Array of Hashes).
|
246
|
+
#
|
247
|
+
# :logic - [String, Symbol] default: 'or' [:or | :and] logic for the scope-query.
|
248
|
+
# Applies to a single query hash.
|
249
|
+
# The reverse logic is applied to an array of query hashes.
|
250
|
+
#
|
251
|
+
# :user - [String] (nil) default: nil, user_id of the Slack user to query against.
|
252
|
+
# Leave blank for non-user queries.
|
253
|
+
#
|
254
|
+
# :base - [Hash] default: nil, a set of scopes to query against
|
255
|
+
# defaults to the awarded scopes on this token.
|
256
|
+
#
|
257
|
+
# freeform_hash - [**Hash] default: {}, interpreted as single scope query hash.
|
258
|
+
#
|
259
|
+
def has_scope?(*freeform_array, query: nil, logic:'or', user:nil, base:nil, **freeform_hash)
|
260
|
+
#OmniAuth.logger.debug({freeform_array:freeform_array, freeform_hash:freeform_hash, query:query, logic:logic, user:user, base:base})
|
261
|
+
debug{{freeform_array:freeform_array, freeform_hash:freeform_hash, query:query, logic:logic, user:user, base:base}}
|
262
|
+
|
263
|
+
query ||= case
|
264
|
+
#when simple_string; {classic: simple_string}
|
265
|
+
when freeform_array.any?; freeform_array
|
266
|
+
when freeform_hash.any?; freeform_hash
|
267
|
+
end
|
268
|
+
return unless query
|
269
|
+
|
270
|
+
query = [query].flatten if query.is_a?(Array) || query.is_a?(String)
|
271
|
+
|
272
|
+
user ||= user_id
|
273
|
+
debug{"using user '#{user}' and query '#{query}'"}
|
274
|
+
|
275
|
+
is_identity_query = case query
|
276
|
+
when Hash
|
277
|
+
query.keys.detect{|k| k.to_s == 'identity'}
|
278
|
+
when Array
|
279
|
+
query.detect{ |q| q.is_a?(Hash) && q.keys.detect{|k| k.to_s == 'identity'} }
|
280
|
+
end
|
281
|
+
|
282
|
+
base ||= case
|
283
|
+
when user && is_identity_query
|
284
|
+
#debug{"calling all_scopes(user=#{user}) to build base-scopes"}
|
285
|
+
all_scopes(user)
|
286
|
+
else
|
287
|
+
#debug{"calling all_scopes to build base-scopes"}
|
288
|
+
all_scopes
|
289
|
+
end
|
290
|
+
|
291
|
+
#debug{{freeform_array:freeform_array, freeform_hash:freeform_hash, query:query, logic:logic, user:user, base:base}}
|
292
|
+
self.class.has_scope?(scope_query:query, scope_base:base, logic:logic)
|
293
|
+
end
|
294
|
+
|
295
|
+
# Matches the given scope_query against the given scope_base, with the given logic.
|
296
|
+
#
|
297
|
+
# This is classic and workspace token compatible.
|
298
|
+
#
|
299
|
+
# keywords - All arguments are keyword arguments:
|
300
|
+
#
|
301
|
+
# :scope_query - [Hash, Array of hashes] default: {}.
|
302
|
+
# If scope_query is a string, it will be interpreted as {classic: scope-query-string}.
|
303
|
+
#
|
304
|
+
# key - Symbol of scope type, can be:
|
305
|
+
# [app_home|team|channel|group|mpim|im|identity|classic].
|
306
|
+
#
|
307
|
+
# value - Array or String of individual scopes.
|
308
|
+
#
|
309
|
+
# :scope_base - [Hash] defaul: {}, represents the set of scopes to query against.
|
310
|
+
#
|
311
|
+
# :logic - [String, Symbol] default: or. One of [and|or].
|
312
|
+
# Applies to a single query hash.
|
313
|
+
# The reverse logic is applied to an array of query hashes.
|
314
|
+
#
|
315
|
+
# Examples
|
316
|
+
#
|
317
|
+
# has_scope?(scope_query: {channel: 'channels:read chat:write'})
|
318
|
+
# has_scope?(scope_query: [{identity:'uers:read', channel:'chat:write'}, {app_home:'chat:write'}], logic:'and')
|
319
|
+
# has_scope?(scope_query: 'identity:users identity:team identity:avatar')
|
320
|
+
#
|
321
|
+
def self.has_scope?(scope_query:{}, scope_base:{}, logic:'or')
|
322
|
+
debug{"class-level scope_query '#{scope_query}' scope_base '#{scope_base}' logic '#{logic}'"}
|
323
|
+
_scope_query = scope_query.is_a?(String) ? {classic: scope_query} : scope_query
|
324
|
+
_scope_query = [_scope_query].flatten
|
325
|
+
|
326
|
+
# Converts array of unknown strings to uniform hash of classic:[array-of-scope-strings].
|
327
|
+
if _scope_query.is_a?(Array)
|
328
|
+
new_query = []
|
329
|
+
classic_array = []
|
330
|
+
_scope_query.each_with_index do |q,n|
|
331
|
+
if q.is_a?(String)
|
332
|
+
classic_array.concat(q.words)
|
333
|
+
debug{"building classic_array with words from string '#{q.words}' to give: #{classic_array}"}
|
334
|
+
else
|
335
|
+
new_query << _scope_query[n]
|
336
|
+
end
|
337
|
+
end
|
338
|
+
if classic_array.any?
|
339
|
+
new_query.unshift({classic: classic_array.flatten.uniq})
|
340
|
+
end
|
341
|
+
_scope_query = new_query
|
342
|
+
end
|
343
|
+
|
344
|
+
_scope_base = scope_base
|
345
|
+
raise "scope_base must be a hash" unless (_scope_base.is_a?(Hash) || _scope_base.respond_to?(:to_h))
|
346
|
+
|
347
|
+
out=false
|
348
|
+
|
349
|
+
_logic = case
|
350
|
+
when logic.to_s.downcase == 'or'; {outter: 'all?', inner: 'any?'}
|
351
|
+
when logic.to_s.downcase == 'and'; {outter: 'any?', inner: 'all?'}
|
352
|
+
else {outter: 'all?', inner: 'any?'}
|
353
|
+
end
|
354
|
+
debug{"_logic #{_logic.inspect}"}
|
355
|
+
debug{"_scope_query #{_scope_query}"}
|
356
|
+
|
357
|
+
_scope_query.send(_logic[:outter]) do |query|
|
358
|
+
debug{"outter query: #{_scope_query.inspect}"}
|
359
|
+
|
360
|
+
query.send(_logic[:inner]) do |section, scopes|
|
361
|
+
test_scopes = case
|
362
|
+
when scopes.is_a?(String); scopes.words
|
363
|
+
when scopes.is_a?(Array); scopes
|
364
|
+
else raise "Scope data must be a string or array of strings, like this {team: 'chat:write,team:read', channels: ['channels:read', 'chat:write']}"
|
365
|
+
end
|
366
|
+
|
367
|
+
test_scopes.send(_logic[:inner]) do |scope|
|
368
|
+
debug{"inner query section: #{section.to_s}, scope: #{scope}"}
|
369
|
+
out = _scope_base.to_h[section.to_s].to_a.include?(scope.to_s)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
end # scope_query.send outter-query
|
374
|
+
debug{"output: #{out}"}
|
375
|
+
return out
|
376
|
+
|
377
|
+
end # self.has_scope?
|
378
|
+
|
379
|
+
end # AccessToken
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'oauth2/client'
|
2
|
+
require 'oauth2/response'
|
3
|
+
require 'omniauth'
|
4
|
+
require 'omniauth-slack/debug'
|
5
|
+
require 'omniauth-slack/oauth2/access_token'
|
6
|
+
require 'omniauth-slack/omniauth/auth_hash'
|
7
|
+
|
8
|
+
module OmniAuth
|
9
|
+
module Slack
|
10
|
+
module OAuth2
|
11
|
+
class Client < ::OAuth2::Client
|
12
|
+
|
13
|
+
include OmniAuth::Slack::Debug
|
14
|
+
|
15
|
+
#using StringRefinements
|
16
|
+
#using OAuth2Refinements
|
17
|
+
|
18
|
+
# If this is an array, request history will be stored.
|
19
|
+
# Only store request history if each Client instance is relatively short-lived.
|
20
|
+
#
|
21
|
+
# From your app, you can set this:
|
22
|
+
# OmniAuth::Slack::OAuth2::Client::HISTORY_DEFAULT ||= []
|
23
|
+
#
|
24
|
+
# Then, in your authorization callback action, you can direct
|
25
|
+
# the OAuth2::Client request history to the AuthHash#['extra']['raw_info']:
|
26
|
+
# @auth_hash = env['omniauth.auth']
|
27
|
+
# @access_token = env['omniauth.strategy'].access_token
|
28
|
+
# @access_token.client.history = @auth_hash.extra.raw_info
|
29
|
+
#
|
30
|
+
# TODO: The above seems a little messy. Maybe use a proc
|
31
|
+
# to rediredct Client request history to wherever.
|
32
|
+
# Or maybe don't offer any history storage at all.
|
33
|
+
#
|
34
|
+
HISTORY_DEFAULT=nil
|
35
|
+
SUBDOMAIN_DEFAULT=nil
|
36
|
+
|
37
|
+
attr_accessor :logger, :history, :subdomain
|
38
|
+
|
39
|
+
def initialize(*args, **options)
|
40
|
+
debug{"args: #{args}"}
|
41
|
+
super
|
42
|
+
self.logger = OmniAuth.logger
|
43
|
+
self.history ||= (options[:history] || HISTORY_DEFAULT)
|
44
|
+
# Moved 'dup' to it's own line, cuz we can't dup nil in older ruby version.
|
45
|
+
self.history && self.history = self.history.dup
|
46
|
+
self.subdomain ||= options[:subdomain] || SUBDOMAIN_DEFAULT
|
47
|
+
end
|
48
|
+
|
49
|
+
# Wraps OAuth2::Client#get_token to pass in the omniauth-slack AccessToken class.
|
50
|
+
def get_token(params, access_token_opts = {}, access_token_class = OmniAuth::Slack::OAuth2::AccessToken) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
51
|
+
debug{"params #{params}, access_token_opts #{access_token_opts}"}
|
52
|
+
rslt = super(params, access_token_opts, access_token_class)
|
53
|
+
debug{"Client #{self} built AccessToken #{rslt}"}
|
54
|
+
rslt
|
55
|
+
end
|
56
|
+
|
57
|
+
# Logs each API request and stores the API result in History array (if exists).
|
58
|
+
#
|
59
|
+
# Storage can be disabled by setting client_options: {history: false}.
|
60
|
+
# Storage can be enabled by setting client_options: {history: Array.new}.
|
61
|
+
# Storage is enabled by default, when client is created from Strategy.
|
62
|
+
#
|
63
|
+
#
|
64
|
+
def request(*args)
|
65
|
+
logger.debug "(slack) API request '#{args[0..1]}'." # in thread '#{Thread.current.object_id}'." # by Client '#{self}'
|
66
|
+
debug{"API request args #{args}"}
|
67
|
+
request_output = super(*args)
|
68
|
+
uri = args[1].to_s.gsub(/^.*\/([^\/]+)/, '\1') # use single-quote or double-back-slash for replacement.
|
69
|
+
if history.is_a?(Array)
|
70
|
+
debug{"Saving response to history object #{history.object_id}"}
|
71
|
+
history << OmniAuth::Slack::AuthHash.new(
|
72
|
+
{api_call: uri.to_s, time: Time.now, response: request_output}
|
73
|
+
)
|
74
|
+
end
|
75
|
+
#debug{"API response (#{args[0..1]}) #{request_output.class}"}
|
76
|
+
debug{"API response #{request_output.response.env.body}"}
|
77
|
+
request_output
|
78
|
+
end
|
79
|
+
|
80
|
+
# Wraps #site to insert custom subdomain for API calls.
|
81
|
+
def site(*args)
|
82
|
+
if !@subdomain.to_s.empty?
|
83
|
+
site_uri = URI.parse(super)
|
84
|
+
site_uri.host = "#{@subdomain}.#{site_uri.host}"
|
85
|
+
logger.debug "(slack) Oauth site uri with custom team_domain #{site_uri}"
|
86
|
+
site_uri.to_s
|
87
|
+
else
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|