diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 72bf5778..14a82b1b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2020-08-24 10:08:11 -0400 using RuboCop version 0.82.0. +# on 2021-07-02 14:09:35 -0400 using RuboCop version 0.82.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -26,9 +26,9 @@ Metrics/AbcSize: # Offense count: 2 # Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: - Max: 9 + Max: 10 -# Offense count: 14 +# Offense count: 12 # Configuration parameters: CountComments, ExcludedMethods. Metrics/MethodLength: Max: 32 @@ -41,7 +41,7 @@ Metrics/ParameterLists: # Offense count: 1 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: - Max: 9 + Max: 10 # Offense count: 2 # Cop supports --auto-correct. @@ -58,7 +58,7 @@ RSpec/ContextMethod: - 'spec/slack/web/api/mixins/groups_spec.rb' - 'spec/slack/web/api/mixins/users_spec.rb' -# Offense count: 72 +# Offense count: 78 # Configuration parameters: Prefixes. # Prefixes: when, with, without RSpec/ContextWording: @@ -70,12 +70,12 @@ RSpec/ContextWording: RSpec/EmptyLineAfterExample: Enabled: false -# Offense count: 66 +# Offense count: 64 # Configuration parameters: Max. RSpec/ExampleLength: Enabled: false -# Offense count: 18 +# Offense count: 16 # Configuration parameters: CustomTransform, IgnoreMethods. RSpec/FilePath: Enabled: false @@ -88,7 +88,7 @@ RSpec/InstanceVariable: - 'spec/slack/real_time/client_spec.rb' - 'spec/slack/slack_spec.rb' -# Offense count: 77 +# Offense count: 61 # Configuration parameters: . # SupportedStyles: have_received, receive RSpec/MessageSpies: @@ -98,13 +98,13 @@ RSpec/MessageSpies: RSpec/MultipleExpectations: Max: 5 -# Offense count: 2 +# Offense count: 3 # Configuration parameters: IgnoreSharedExamples. RSpec/NamedSubject: Exclude: - 'spec/slack/web/api/mixins/conversations_list_spec.rb' -# Offense count: 37 +# Offense count: 48 RSpec/NestedGroups: Max: 6 @@ -116,7 +116,7 @@ RSpec/SubjectStub: - 'spec/slack/web/api/mixins/groups_spec.rb' - 'spec/slack/web/api/mixins/users_spec.rb' -# Offense count: 16 +# Offense count: 12 # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: Exclude: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8640dc17..a59a89e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ### 0.18.0 (Next) * Your contribution here. +* [#382](https://github.com/slack-ruby/slack-ruby-client/pull/382): Add option to extract OAuth scopes from Web response headers - [@jmanian](https://github.com/jmanian). * [#380](https://github.com/slack-ruby/slack-ruby-client/pull/380): Updates to server error classes and hierarchy - [@jmanian](https://github.com/jmanian). ### 0.17.0 (2021/03/07) diff --git a/README.md b/README.md index ccea8b01..ab3d14b7 100644 --- a/README.md +++ b/README.md @@ -239,6 +239,7 @@ open_timeout | Optional connection open timeout in seconds. default_page_size | Optional page size for paginated requests, default is _100_. default_max_retries | Optional number of retries for paginated requests, default is _100_. adapter | Optional HTTP adapter to use, defaults to `Faraday.default_adapter`. +store_scopes | Option to populate `oauth_scopes` on the client from the response headers after a request. You can also pass request options, including `timeout` and `open_timeout` into individual calls. diff --git a/lib/slack-ruby-client.rb b/lib/slack-ruby-client.rb index 54c351db..3cf513c8 100644 --- a/lib/slack-ruby-client.rb +++ b/lib/slack-ruby-client.rb @@ -31,6 +31,7 @@ require_relative 'slack/web/api/errors/server_error' require_relative 'slack/web/faraday/response/raise_error' require_relative 'slack/web/faraday/response/wrap_error' +require_relative 'slack/web/faraday/response/store_scopes' require_relative 'slack/web/faraday/connection' require_relative 'slack/web/faraday/request' require_relative 'slack/web/api/mixins' diff --git a/lib/slack/web/client.rb b/lib/slack/web/client.rb index b2d253e2..346d9632 100644 --- a/lib/slack/web/client.rb +++ b/lib/slack/web/client.rb @@ -6,7 +6,7 @@ class Client include Faraday::Request include Api::Endpoints - attr_accessor(*Config::ATTRIBUTES) + attr_accessor(*Config::ATTRIBUTES, :oauth_scopes) def initialize(options = {}) Slack::Web::Config::ATTRIBUTES.each do |key| diff --git a/lib/slack/web/config.rb b/lib/slack/web/config.rb index 0f0cc42a..dd0db940 100644 --- a/lib/slack/web/config.rb +++ b/lib/slack/web/config.rb @@ -17,6 +17,7 @@ module Config default_page_size default_max_retries adapter + store_scopes ].freeze attr_accessor(*Config::ATTRIBUTES) @@ -34,6 +35,7 @@ def reset self.default_page_size = 100 self.default_max_retries = 100 self.adapter = ::Faraday.default_adapter + self.store_scopes = nil end end diff --git a/lib/slack/web/faraday/connection.rb b/lib/slack/web/faraday/connection.rb index 5f461b5e..18e71e1c 100644 --- a/lib/slack/web/faraday/connection.rb +++ b/lib/slack/web/faraday/connection.rb @@ -28,6 +28,7 @@ def connection connection.use ::FaradayMiddleware::Mashify, mash_class: Slack::Messages::Message connection.use ::FaradayMiddleware::ParseJson connection.use ::Slack::Web::Faraday::Response::WrapError + connection.use ::Slack::Web::Faraday::Response::StoreScopes, client: self if store_scopes connection.response :logger, logger if logger connection.adapter adapter end diff --git a/lib/slack/web/faraday/response/store_scopes.rb b/lib/slack/web/faraday/response/store_scopes.rb new file mode 100644 index 00000000..d7c4f018 --- /dev/null +++ b/lib/slack/web/faraday/response/store_scopes.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +module Slack + module Web + module Faraday + module Response + class StoreScopes < ::Faraday::Response::Middleware + attr_accessor :client + + def initialize(app = nil, options = {}) + super(app) + self.client = options[:client] + end + + def on_complete(env) + raw_scopes = env.response_headers[:'x-oauth-scopes'] + client.oauth_scopes = raw_scopes&.split(',') + end + end + end + end + end +end diff --git a/spec/lib/slack/web/faraday/response/store_scopes_spec.rb b/spec/lib/slack/web/faraday/response/store_scopes_spec.rb new file mode 100644 index 00000000..7935c669 --- /dev/null +++ b/spec/lib/slack/web/faraday/response/store_scopes_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe Slack::Web::Faraday::Response::StoreScopes do + let(:store_scopes_obj) { described_class.new(app, client: client) } + let(:app) { proc {} } + let(:client) { Slack::Web::Client.new } + let(:env) { instance_double(Faraday::Env, response_headers: response_headers) } + + describe '#on_complete' do + subject(:on_complete) { store_scopes_obj.on_complete(env) } + + context 'with no x-oauth-scopes header' do + let(:response_headers) { Faraday::Utils::Headers.new } + + it 'does not set oauth_scopes on the client' do + on_complete + expect(client.oauth_scopes).to be_nil + end + end + + context 'with x-oauth-scopes in an unexpected format' do + let(:raw_scopes) { 'this is not what scopes look like' } + let(:response_headers) { Faraday::Utils::Headers.new('x-oauth-scopes': raw_scopes) } + + it 'does not crash' do + on_complete + expect(client.oauth_scopes).to contain_exactly(raw_scopes) + end + end + + context 'with x-oauth-scopes in an expected format' do + let(:scopes) { %w[chat:write chat:write.public chat:write:user commands identity.basic] } + let(:response_headers) { Faraday::Utils::Headers.new('x-oauth-scopes': scopes.join(',')) } + + it 'parses the scopes into an array' do + on_complete + expect(client.oauth_scopes).to match_array(scopes) + end + end + end +end