Class: OmniAuth::Slack::OAuth2::AccessToken
- Inherits:
-
OAuth2::AccessToken
- Object
- OAuth2::AccessToken
- OmniAuth::Slack::OAuth2::AccessToken
- Includes:
- Debug
- Defined in:
- lib/omniauth-slack/oauth2/access_token.rb
Overview
This is an enhanced subclass of OAuth2::AccessToken. It handles Slack-specific data and behavior, and it also adds a scope-query method has_scope?
The AccessToken object is built with the hash returned from the get-token API request or is passed in manually via AccessToken.from_hash() or OmniAuth::Slack::build_access_token.
The original hash from the API can always be found at AccessToken#params. As a convenience, you can call '[]' on the params hash by sending the method and args directly to the access-token object.
my_token['ok'] --> true
my_token['app_id'] --> A012345678
The AccessToken instance provides getter methods for top-level data points of the returned token hash. See define_getters call below for more convenience methods.
See Slack's documentation for the different types of tokens available.
Constant Summary
Constants included from Debug
Debug::LOG_ALL, Debug::LOG_NONE
Class Method Summary collapse
-
.define_getters(ary_of_words) ⇒ Object
Creates simple getter methods to pull specific data from the raw token hash.
-
.has_scope?(scope_query: {}, scope_base: {}, logic: 'or') ⇒ Boolean
Matches the given scope_query against the given scope_base, with the given logic.
Instance Method Summary collapse
-
#all_scopes ⇒ Object
(also: #scopes)
Compiles scopes awarded to this AccessToken.
-
#app_user_id ⇒ Object
Gets the app_user_id if it exists.
-
#bot_user_id ⇒ Object
Gets bot_user_id if it exists.
-
#has_scope?(*freeform_array, query: nil, logic: 'or', user: nil, base: nil, **freeform_hash) ⇒ Boolean
Match a given set of scopes against this token's awarded scopes, classic and workspace token compatible.
-
#ok? ⇒ Boolean
Check's the token hash 'ok' field.
-
#to_auth_hash ⇒ Object
Experimental, converts this AccessToken instance to an AuthHash object.
-
#token ⇒ Object
Intercepts super to return nil instead of an empty string.
-
#token_type ⇒ Object
Inspects the token and determines token type.
-
#token_type?(*_type) ⇒ Boolean
Compares given token type with actual token_type.
-
#uid ⇒ Object
Gets the AccessToken unique user-team-id combo, if it can be determined.
-
#user_id ⇒ Object
Gets the AccessToken person-user-id if it exists.
-
#user_name ⇒ Object
Gets user_name from wherever it can be found in the returned token, regardless of what type of token is returned.
-
#user_token ⇒ Object
(also: #authed_user)
Converts 'authed_user' hash (of Slack v2 oauth flow) to AccessToken object.
Methods included from Debug
Methods included from CallerMethodName
Class Method Details
.define_getters(ary_of_words) ⇒ Object
Creates simple getter methods to pull specific data from the raw token hash.
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 40 def self.define_getters(ary_of_words) ary_of_words.each do |word| obj, atrb = word.split('_') define_method(word) do rslt = ( params[word] || params && params[obj] && params[obj][atrb] ) debug { "Simple getter '#{word}' rslt: #{rslt}" } rslt end end end |
.has_scope?(scope_query: {}, scope_base: {}, logic: 'or') ⇒ Boolean
Matches the given scope_query against the given scope_base, with the given logic.
This is classic and workspace token compatible.
keywords - All arguments are keyword arguments:
:scope_query - [Hash, Array of hashes] default: {}. If scope_query is a string, it will be interpreted as scope-query-string.
key - Symbol of scope type, can be:
[app_home|team|channel|group|mpim|im|identity|classic].
value - Array or String of individual scopes.
:scope_base - [Hash] defaul: {}, represents the set of scopes to query against.
:logic - [String, Symbol] default: or. One of [and|or]. Applies to a single query hash. The reverse logic is applied to an array of query hashes.
Examples
has_scope?(scope_query: 'channels:read chat:write') has_scope?(scope_query: [channel:'chat:write', app_home:'chat:write'], logic:'and') has_scope?(scope_query: 'identity:users identity:team identity:avatar')
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 321 def self.has_scope?(scope_query:{}, scope_base:{}, logic:'or') debug{"class-level scope_query '#{scope_query}' scope_base '#{scope_base}' logic '#{logic}'"} _scope_query = scope_query.is_a?(String) ? {classic: scope_query} : scope_query _scope_query = [_scope_query].flatten # Converts array of unknown strings to uniform hash of classic:[array-of-scope-strings]. if _scope_query.is_a?(Array) new_query = [] classic_array = [] _scope_query.each_with_index do |q,n| if q.is_a?(String) classic_array.concat(q.words) debug{"building classic_array with words from string '#{q.words}' to give: #{classic_array}"} else new_query << _scope_query[n] end end if classic_array.any? new_query.unshift({classic: classic_array.flatten.uniq}) end _scope_query = new_query end _scope_base = scope_base raise "scope_base must be a hash" unless (_scope_base.is_a?(Hash) || _scope_base.respond_to?(:to_h)) out=false _logic = case when logic.to_s.downcase == 'or'; {outter: 'all?', inner: 'any?'} when logic.to_s.downcase == 'and'; {outter: 'any?', inner: 'all?'} else {outter: 'all?', inner: 'any?'} end debug{"_logic #{_logic.inspect}"} debug{"_scope_query #{_scope_query}"} _scope_query.send(_logic[:outter]) do |query| debug{"outter query: #{_scope_query.inspect}"} query.send(_logic[:inner]) do |section, scopes| test_scopes = case when scopes.is_a?(String); scopes.words when scopes.is_a?(Array); scopes else raise "Scope data must be a string or array of strings, like this {team: 'chat:write,team:read', channels: ['channels:read', 'chat:write']}" end test_scopes.send(_logic[:inner]) do |scope| debug{"inner query section: #{section.to_s}, scope: #{scope}"} out = _scope_base.to_h[section.to_s].to_a.include?(scope.to_s) end end end # scope_query.send outter-query debug{"output: #{out}"} return out end |
Instance Method Details
#all_scopes ⇒ Object Also known as: scopes
Compiles scopes awarded to this AccessToken.
Returns hash of scope arrays where key is scope section and value is Array of scopes.
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 222 def all_scopes @all_scopes ||= ( case when ! params['scope'].to_s.empty? {'classic' => params['scope'].words} when params['scopes'].to_h.any? params['scopes'] end ) end |
#app_user_id ⇒ Object
Gets the app_user_id if it exists.
Returns string or nil.
205 206 207 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 205 def app_user_id params['app_user_id'] end |
#bot_user_id ⇒ Object
Gets bot_user_id if it exists.
Returns string or nil.
197 198 199 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 197 def bot_user_id params['bot_user_id'] end |
#has_scope?(*freeform_array, query: nil, logic: 'or', user: nil, base: nil, **freeform_hash) ⇒ Boolean
Match a given set of scopes against this token's awarded scopes, classic and workspace token compatible.
If the scope-query is a string, it will be interpreted as a Slack Classic App scope string scope-query-string, even if the token is a v2 token.
The keywords need to be symbols, so any hash passed as an argument (or as the entire set of args) should have symbolized keys!
freeform_array - [*Array, nil] default: [], array of scope query hashes or string(s).
:query - [Hash, Array, nil] default: nil, a single scope-query Hash (or Array of Hashes).
:logic - [String, Symbol] default: 'or' [:or | :and] logic for the scope-query. Applies to a single query hash. The reverse logic is applied to an array of query hashes.
:user - String default: nil, user_id of the Slack user to query against. Leave blank for non-user queries.
:base - [Hash] default: nil, a set of scopes to query against defaults to the awarded scopes on this token.
freeform_hash - [**Hash] default: {}, interpreted as single scope query hash.
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 259 def has_scope?(*freeform_array, query: nil, logic:'or', user:nil, base:nil, **freeform_hash) #OmniAuth.logger.debug({freeform_array:freeform_array, freeform_hash:freeform_hash, query:query, logic:logic, user:user, base:base}) debug{{freeform_array:freeform_array, freeform_hash:freeform_hash, query:query, logic:logic, user:user, base:base}} query ||= case #when simple_string; {classic: simple_string} when freeform_array.any?; freeform_array when freeform_hash.any?; freeform_hash end return unless query query = [query].flatten if query.is_a?(Array) || query.is_a?(String) user ||= user_id debug{"using user '#{user}' and query '#{query}'"} is_identity_query = case query when Hash query.keys.detect{|k| k.to_s == 'identity'} when Array query.detect{ |q| q.is_a?(Hash) && q.keys.detect{|k| k.to_s == 'identity'} } end base ||= case when user && is_identity_query #debug{"calling all_scopes(user=#{user}) to build base-scopes"} all_scopes(user) else #debug{"calling all_scopes to build base-scopes"} all_scopes end #debug{{freeform_array:freeform_array, freeform_hash:freeform_hash, query:query, logic:logic, user:user, base:base}} self.class.has_scope?(scope_query:query, scope_base:base, logic:logic) end |
#ok? ⇒ Boolean
Check's the token hash 'ok' field.
Returns true or false, representing the success status of the token response.
71 72 73 74 75 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 71 def ok? params['ok'] == true || params['ok'].to_s[/true/i] || false end |
#to_auth_hash ⇒ Object
Experimental, converts this AccessToken instance to an AuthHash object.
Returns OmniAuth::Slack::AuthHash instance.
213 214 215 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 213 def to_auth_hash Module.const_get('::OmniAuth::Slack::AuthHash').new(params) end |
#token ⇒ Object
Intercepts super to return nil instead of an empty string.
Returns the token string or nil.
81 82 83 84 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 81 def token rslt = super rslt.to_s == '' ? nil : rslt end |
#token_type ⇒ Object
Inspects the token and determines token type.
Returns a string representing token type.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 90 def token_type params['token_type'] || case when params['token_type'] == 'user' || @token.to_s[/xoxp/]; 'user' when params['token_type'] == 'bot' || @token.to_s[/xoxb/]; 'bot' when params['token_type'] == 'app' || @token.to_s[/xoxa/]; 'app' when @token.to_s[/xoxr/]; 'refresh' end end |
#token_type?(*_type) ⇒ Boolean
Compares given token type with actual token_type.
Returns true if given type matches actual token_type, otherwise false.
111 112 113 114 115 116 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 111 def token_type?(*_type) #debug{"'#{_type}'"} [_type].flatten.any? do |t| token_type.to_s == t.to_s end || false end |
#uid ⇒ Object
Gets the AccessToken unique user-team-id combo, if it can be determined.
Returns string or nil.
165 166 167 168 169 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 165 def uid rslt = (user_id && team_id) ? "#{user_id}-#{team_id}" : nil debug { rslt } rslt end |
#user_id ⇒ Object
Gets the AccessToken person-user-id if it exists.
Returns string or nil.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 140 def user_id rslt = ( # classic token. params['user_id'] || # from sub-token in 'authed_user' params['authed_user'].to_h['id'] || # workspace-app token with attached user. params['user'].to_h['id'] || # workspace-app token with authorizing user. params['authorizing_user'].to_h['user_id'] || # workspace-app token with installer user. params['installer_user'].to_h['user_id'] || # user-id from authed_user hash. params['id'] #|| # v2 api bot token, as a last resort. #params['bot_user_id'] ) debug { rslt } rslt end |
#user_name ⇒ Object
Gets user_name from wherever it can be found in the returned token, regardless of what type of token is returned.
Returns string or nil.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 176 def user_name params['user_name'] || # from sub-token in 'authed_user' params['authed_user'].to_h['name'] || # workspace-app token with attached user. params['user'].to_h['name'] || # from authed_user hash. params['name'] || # workspace token with authorizing user. params['authorizing_user'].to_h['name'] || # workspace token with installer user. params['installer_user'].to_h['name'] || # more workspace token possibilities. to_auth_hash.deep_find('nickname') || to_auth_hash.deep_find('real_name') end |
#user_token ⇒ Object Also known as: authed_user
Converts 'authed_user' hash (of Slack v2 oauth flow) to AccessToken object.
Returns an AccessToken instance or nil.
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/omniauth-slack/oauth2/access_token.rb', line 122 def user_token @user_token ||= ( if token_type?('user') self elsif params['authed_user'] rslt = self.class.from_hash(client, params['authed_user']).tap do |t| t.params['token_type'] = 'user' t.params['team_id'] = team_id end end ) end |