diff --git a/.github/workflows/plugin-linting.yml b/.github/workflows/plugin-linting.yml index c807794..6d2bb97 100644 --- a/.github/workflows/plugin-linting.yml +++ b/.github/workflows/plugin-linting.yml @@ -55,3 +55,12 @@ jobs: - name: Rubocop if: ${{ !cancelled() }} run: bundle exec rubocop . + + - name: Syntax Tree + if: ${{ !cancelled() }} + run: | + if test -f .streerc; then + bundle exec stree check Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') + else + echo "Stree config not detected for this repository. Skipping." + fi diff --git a/.github/workflows/plugin-tests.yml b/.github/workflows/plugin-tests.yml index 9d390bc..f30a5be 100644 --- a/.github/workflows/plugin-tests.yml +++ b/.github/workflows/plugin-tests.yml @@ -80,7 +80,7 @@ jobs: - name: Get yarn cache directory id: yarn-cache-dir - run: echo "::set-output name=dir::$(yarn cache dir)" + run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT - name: Yarn cache uses: actions/cache@v3 @@ -130,7 +130,7 @@ jobs: shell: bash run: | if [ 0 -lt $(find plugins/${{ github.event.repository.name }}/spec -type f -name "*.rb" 2> /dev/null | wc -l) ]; then - echo "::set-output name=files_exist::true" + echo "files_exist=true" >> $GITHUB_OUTPUT fi - name: Plugin RSpec @@ -142,7 +142,7 @@ jobs: shell: bash run: | if [ 0 -lt $(find plugins/${{ github.event.repository.name }}/test/javascripts -type f \( -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then - echo "::set-output name=files_exist::true" + echo "files_exist=true" >> $GITHUB_OUTPUT fi - name: Plugin QUnit diff --git a/.rubocop.yml b/.rubocop.yml index d46296c..fb14dfa 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,2 @@ inherit_gem: - rubocop-discourse: default.yml + rubocop-discourse: stree-compat.yml diff --git a/.streerc b/.streerc new file mode 100644 index 0000000..0bc4379 --- /dev/null +++ b/.streerc @@ -0,0 +1,2 @@ +--print-width=100 +--plugins=plugin/trailing_comma diff --git a/Gemfile b/Gemfile index 7da32ec..31d8bf7 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,8 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" group :development do - gem 'rubocop-discourse' + gem "rubocop-discourse" + gem "syntax_tree" end diff --git a/Gemfile.lock b/Gemfile.lock index 2434c95..3b79e02 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,6 +6,7 @@ GEM parallel (1.22.1) parser (3.1.2.1) ast (~> 2.4.1) + prettier_print (1.2.0) rainbow (3.1.1) regexp_parser (2.6.0) rexml (3.2.5) @@ -27,6 +28,8 @@ GEM rubocop-rspec (2.13.2) rubocop (~> 1.33) ruby-progressbar (1.11.0) + syntax_tree (5.1.0) + prettier_print (>= 1.2.0) unicode-display_width (2.3.0) PLATFORMS @@ -39,6 +42,7 @@ PLATFORMS DEPENDENCIES rubocop-discourse + syntax_tree BUNDLED WITH 2.3.10 diff --git a/plugin.rb b/plugin.rb index 1545dc0..c5e4dcb 100644 --- a/plugin.rb +++ b/plugin.rb @@ -13,19 +13,19 @@ class ::OmniAuth::Strategies::Oauth2Basic < ::OmniAuth::Strategies::OAuth2 option :name, "oauth2_basic" uid do - if path = SiteSetting.oauth2_callback_user_id_path.split('.') + if path = SiteSetting.oauth2_callback_user_id_path.split(".") recurse(access_token, [*path]) if path.present? end end info do - if paths = SiteSetting.oauth2_callback_user_info_paths.split('|') + if paths = SiteSetting.oauth2_callback_user_info_paths.split("|") result = Hash.new paths.each do |p| - segments = p.split(':') + segments = p.split(":") if segments.length == 2 key = segments.first - path = [*segments.last.split('.')] + path = [*segments.last.split(".")] result[key] = recurse(access_token, path) end end @@ -45,7 +45,7 @@ class ::OmniAuth::Strategies::Oauth2Basic < ::OmniAuth::Strategies::OAuth2 end end -require 'faraday/logging/formatter' +require "faraday/logging/formatter" class OAuth2FaradayFormatter < Faraday::Logging::Formatter def request(env) warn <<~LOG @@ -76,7 +76,7 @@ DiscoursePluginRegistry.define_filtered_register :oauth2_basic_additional_json_p class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator def name - 'oauth2_basic' + "oauth2_basic" end def can_revoke? @@ -90,52 +90,66 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator def register_middleware(omniauth) omniauth.provider :oauth2_basic, name: name, - setup: lambda { |env| - opts = env['omniauth.strategy'].options - opts[:client_id] = SiteSetting.oauth2_client_id - opts[:client_secret] = SiteSetting.oauth2_client_secret - opts[:provider_ignores_state] = SiteSetting.oauth2_disable_csrf - opts[:client_options] = { - authorize_url: SiteSetting.oauth2_authorize_url, - token_url: SiteSetting.oauth2_token_url, - token_method: SiteSetting.oauth2_token_url_method.downcase.to_sym - } - opts[:authorize_options] = SiteSetting.oauth2_authorize_options.split("|").map(&:to_sym) + setup: + lambda { |env| + opts = env["omniauth.strategy"].options + opts[:client_id] = SiteSetting.oauth2_client_id + opts[:client_secret] = SiteSetting.oauth2_client_secret + opts[:provider_ignores_state] = SiteSetting.oauth2_disable_csrf + opts[:client_options] = { + authorize_url: SiteSetting.oauth2_authorize_url, + token_url: SiteSetting.oauth2_token_url, + token_method: SiteSetting.oauth2_token_url_method.downcase.to_sym, + } + opts[:authorize_options] = SiteSetting + .oauth2_authorize_options + .split("|") + .map(&:to_sym) - if SiteSetting.oauth2_authorize_signup_url.present? && - ActionDispatch::Request.new(env).params["signup"].present? - opts[:client_options][:authorize_url] = SiteSetting.oauth2_authorize_signup_url - end - - if SiteSetting.oauth2_send_auth_header? && SiteSetting.oauth2_send_auth_body? - # For maximum compatibility we include both header and body auth by default - # This is a little unusual, and utilising multiple authentication methods - # is technically disallowed by the spec (RFC2749 Section 5.2) - opts[:client_options][:auth_scheme] = :request_body - opts[:token_params] = { headers: { 'Authorization' => basic_auth_header } } - elsif SiteSetting.oauth2_send_auth_header? - opts[:client_options][:auth_scheme] = :basic_auth - else - opts[:client_options][:auth_scheme] = :request_body - end - - unless SiteSetting.oauth2_scope.blank? - opts[:scope] = SiteSetting.oauth2_scope - end - - opts[:client_options][:connection_build] = lambda { |builder| - if SiteSetting.oauth2_debug_auth && defined? OAuth2FaradayFormatter - builder.response :logger, Rails.logger, { bodies: true, formatter: OAuth2FaradayFormatter } + if SiteSetting.oauth2_authorize_signup_url.present? && + ActionDispatch::Request.new(env).params["signup"].present? + opts[:client_options][ + :authorize_url + ] = SiteSetting.oauth2_authorize_signup_url end - builder.request :url_encoded # form-encode POST params - builder.adapter FinalDestination::FaradayAdapter # make requests with FinalDestination::HTTP + if SiteSetting.oauth2_send_auth_header? && + SiteSetting.oauth2_send_auth_body? + # For maximum compatibility we include both header and body auth by default + # This is a little unusual, and utilising multiple authentication methods + # is technically disallowed by the spec (RFC2749 Section 5.2) + opts[:client_options][:auth_scheme] = :request_body + opts[:token_params] = { + headers: { + "Authorization" => basic_auth_header, + }, + } + elsif SiteSetting.oauth2_send_auth_header? + opts[:client_options][:auth_scheme] = :basic_auth + else + opts[:client_options][:auth_scheme] = :request_body + end + + unless SiteSetting.oauth2_scope.blank? + opts[:scope] = SiteSetting.oauth2_scope + end + + opts[:client_options][:connection_build] = lambda do |builder| + if SiteSetting.oauth2_debug_auth && defined?(OAuth2FaradayFormatter) + builder.response :logger, + Rails.logger, + { bodies: true, formatter: OAuth2FaradayFormatter } + end + + builder.request :url_encoded # form-encode POST params + builder.adapter FinalDestination::FaradayAdapter # make requests with FinalDestination::HTTP + end } - } end def basic_auth_header - "Basic " + Base64.strict_encode64("#{SiteSetting.oauth2_client_id}:#{SiteSetting.oauth2_client_secret}") + "Basic " + + Base64.strict_encode64("#{SiteSetting.oauth2_client_id}:#{SiteSetting.oauth2_client_secret}") end def walk_path(fragment, segments, seg_index = 0) @@ -182,19 +196,21 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator quoted = false escaped = false - path.split("").each do |char| - next_char_escaped = false - if !escaped && (char == '"') - quoted = !quoted - elsif !escaped && !quoted && (char == '.') - segments.append +"" - elsif !escaped && (char == '\\') - next_char_escaped = true - else - segments.last << char + path + .split("") + .each do |char| + next_char_escaped = false + if !escaped && (char == '"') + quoted = !quoted + elsif !escaped && !quoted && (char == ".") + segments.append +"" + elsif !escaped && (char == '\\') + next_char_escaped = true + else + segments.last << char + end + escaped = next_char_escaped end - escaped = next_char_escaped - end segments end @@ -204,14 +220,14 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator end def fetch_user_details(token, id) - user_json_url = SiteSetting.oauth2_user_json_url.sub(':token', token.to_s).sub(':id', id.to_s) + user_json_url = SiteSetting.oauth2_user_json_url.sub(":token", token.to_s).sub(":id", id.to_s) user_json_method = SiteSetting.oauth2_user_json_url_method.downcase.to_sym log("user_json_url: #{user_json_method} #{user_json_url}") bearer_token = "Bearer #{token}" connection = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter } - headers = { 'Authorization' => bearer_token, 'Accept' => 'application/json' } + headers = { "Authorization" => bearer_token, "Accept" => "application/json" } user_json_response = connection.run_request(user_json_method, user_json_url, nil, headers) log("user_json_response: #{user_json_response.inspect}") @@ -243,7 +259,7 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator def primary_email_verified?(auth) return true if SiteSetting.oauth2_email_verified - verified = auth['info']['email_verified'] + verified = auth["info"]["email_verified"] verified = true if verified == "true" verified = false if verified == "false" verified @@ -254,19 +270,25 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator end def after_authenticate(auth, existing_account: nil) - log("after_authenticate response: \n\ncreds: #{auth['credentials'].to_hash}\nuid: #{auth['uid']}\ninfo: #{auth['info'].to_hash}\nextra: #{auth['extra'].to_hash}") + log( + "after_authenticate response: \n\ncreds: #{auth["credentials"].to_hash}\nuid: #{auth["uid"]}\ninfo: #{auth["info"].to_hash}\nextra: #{auth["extra"].to_hash}", + ) if SiteSetting.oauth2_fetch_user_details? - if fetched_user_details = fetch_user_details(auth['credentials']['token'], auth['uid']) - auth['uid'] = fetched_user_details[:user_id] if fetched_user_details[:user_id] - auth['info']['nickname'] = fetched_user_details[:username] if fetched_user_details[:username] - auth['info']['image'] = fetched_user_details[:avatar] if fetched_user_details[:avatar] - ['name', 'email', 'email_verified'].each do |property| - auth['info'][property] = fetched_user_details[property.to_sym] if fetched_user_details[property.to_sym] + if fetched_user_details = fetch_user_details(auth["credentials"]["token"], auth["uid"]) + auth["uid"] = fetched_user_details[:user_id] if fetched_user_details[:user_id] + auth["info"]["nickname"] = fetched_user_details[:username] if fetched_user_details[ + :username + ] + auth["info"]["image"] = fetched_user_details[:avatar] if fetched_user_details[:avatar] + %w[name email email_verified].each do |property| + auth["info"][property] = fetched_user_details[property.to_sym] if fetched_user_details[ + property.to_sym + ] end DiscoursePluginRegistry.oauth2_basic_additional_json_paths.each do |detail| - auth['extra'][detail] = fetched_user_details["extra:#{detail}"] + auth["extra"][detail] = fetched_user_details["extra:#{detail}"] end else result = Auth::Result.new @@ -284,7 +306,9 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator end end -auth_provider title_setting: "oauth2_button_title", - authenticator: OAuth2BasicAuthenticator.new +auth_provider title_setting: "oauth2_button_title", authenticator: OAuth2BasicAuthenticator.new -load File.expand_path("../lib/validators/oauth2_basic/oauth2_fetch_user_details_validator.rb", __FILE__) +load File.expand_path( + "../lib/validators/oauth2_basic/oauth2_fetch_user_details_validator.rb", + __FILE__, + ) diff --git a/spec/integration/overrides_email_spec.rb b/spec/integration/overrides_email_spec.rb index 5f4e1dd..fd7ea91 100644 --- a/spec/integration/overrides_email_spec.rb +++ b/spec/integration/overrides_email_spec.rb @@ -6,7 +6,9 @@ describe "OAuth2 Overrides Email", type: :request do fab!(:initial_email) { "initial@example.com" } fab!(:new_email) { "new@example.com" } fab!(:user) { Fabricate(:user, email: initial_email) } - fab!(:uac) { UserAssociatedAccount.create!(user: user, provider_name: "oauth2_basic", provider_uid: "12345") } + fab!(:uac) do + UserAssociatedAccount.create!(user: user, provider_name: "oauth2_basic", provider_uid: "12345") + end before do SiteSetting.oauth2_enabled = true @@ -16,17 +18,13 @@ describe "OAuth2 Overrides Email", type: :request do OmniAuth.config.test_mode = true OmniAuth.config.mock_auth[:oauth2_basic] = OmniAuth::AuthHash.new( - provider: 'oauth2_basic', - uid: '12345', - info: OmniAuth::AuthHash::InfoHash.new( - email: new_email - ), + provider: "oauth2_basic", + uid: "12345", + info: OmniAuth::AuthHash::InfoHash.new(email: new_email), extra: { - raw_info: OmniAuth::AuthHash.new( - email_verified: true - ) + raw_info: OmniAuth::AuthHash.new(email_verified: true), }, - credentials: OmniAuth::AuthHash.new + credentials: OmniAuth::AuthHash.new, ) end @@ -40,7 +38,7 @@ describe "OAuth2 Overrides Email", type: :request do expect(user.reload.email).to eq(initial_email) end - it 'updates user email if enabled' do + it "updates user email if enabled" do SiteSetting.oauth2_overrides_email = true get "/auth/oauth2_basic/callback" diff --git a/spec/plugin_spec.rb b/spec/plugin_spec.rb index f63837f..4f2cbec 100644 --- a/spec/plugin_spec.rb +++ b/spec/plugin_spec.rb @@ -1,31 +1,36 @@ # frozen_string_literal: true -require 'rails_helper' +require "rails_helper" describe OAuth2BasicAuthenticator do - describe 'after_authenticate' do + describe "after_authenticate" do let(:user) { Fabricate(:user) } let(:authenticator) { OAuth2BasicAuthenticator.new } let(:auth) do - OmniAuth::AuthHash.new('provider' => 'oauth2_basic', - 'credentials' => { 'token': 'token' }, - 'uid' => '123456789', - 'info' => { id: 'id' }, - 'extra' => {}) + OmniAuth::AuthHash.new( + "provider" => "oauth2_basic", + "credentials" => { + token: "token", + }, + "uid" => "123456789", + "info" => { + id: "id", + }, + "extra" => { + }, + ) end - before(:each) do - SiteSetting.oauth2_email_verified = true - end + before(:each) { SiteSetting.oauth2_email_verified = true } - it 'finds user by email' do + it "finds user by email" do authenticator.expects(:fetch_user_details).returns(email: user.email) result = authenticator.after_authenticate(auth) expect(result.user).to eq(user) end - it 'validates user email if provider has verified' do + it "validates user email if provider has verified" do SiteSetting.oauth2_email_verified = false authenticator.stubs(:fetch_user_details).returns(email: user.email, email_verified: true) result = authenticator.after_authenticate(auth) @@ -46,13 +51,13 @@ describe OAuth2BasicAuthenticator do expect(result.email_valid).to eq(true) end - it 'handles true/false strings from identity provider' do + it "handles true/false strings from identity provider" do SiteSetting.oauth2_email_verified = false - authenticator.stubs(:fetch_user_details).returns(email: user.email, email_verified: 'true') + authenticator.stubs(:fetch_user_details).returns(email: user.email, email_verified: "true") result = authenticator.after_authenticate(auth) expect(result.email_valid).to eq(true) - authenticator.stubs(:fetch_user_details).returns(email: user.email, email_verified: 'false') + authenticator.stubs(:fetch_user_details).returns(email: user.email, email_verified: "false") result = authenticator.after_authenticate(auth) expect(result.email_valid).to eq(false) end @@ -61,21 +66,16 @@ describe OAuth2BasicAuthenticator do before(:each) do SiteSetting.oauth2_fetch_user_details = true SiteSetting.oauth2_user_json_url = "https://provider.com/user" - SiteSetting.oauth2_user_json_url_method = 'GET' - SiteSetting.oauth2_json_email_path = 'account.email' + SiteSetting.oauth2_user_json_url_method = "GET" + SiteSetting.oauth2_json_email_path = "account.email" end let(:success_response) do - { - status: 200, - body: '{"account":{"email":"newemail@example.com"}}' - } + { status: 200, body: '{"account":{"email":"newemail@example.com"}}' } end let (:fail_response) do - { - status: 403 - } + { status: 403 } end it "works" do @@ -83,7 +83,7 @@ describe OAuth2BasicAuthenticator do result = authenticator.after_authenticate(auth) expect(result.email).to eq("newemail@example.com") - SiteSetting.oauth2_user_json_url_method = 'POST' + SiteSetting.oauth2_user_json_url_method = "POST" stub_request(:post, SiteSetting.oauth2_user_json_url).to_return(success_response) result = authenticator.after_authenticate(auth) expect(result.email).to eq("newemail@example.com") @@ -94,27 +94,27 @@ describe OAuth2BasicAuthenticator do result = authenticator.after_authenticate(auth) expect(result.failed).to eq(true) - SiteSetting.oauth2_user_json_url_method = 'POST' + SiteSetting.oauth2_user_json_url_method = "POST" stub_request(:post, SiteSetting.oauth2_user_json_url).to_return(fail_response) result = authenticator.after_authenticate(auth) expect(result.failed).to eq(true) end - describe 'fetch custom attributes' do + describe "fetch custom attributes" do after { DiscoursePluginRegistry.reset_register!(:oauth2_basic_additional_json_paths) } let(:response) do { status: 200, - body: '{"account":{"email":"newemail@example.com","custom_attr":"received"}}' + body: '{"account":{"email":"newemail@example.com","custom_attr":"received"}}', } end - it 'stores custom attributes in the user associated account' do - custom_path = 'account.custom_attr' + it "stores custom attributes in the user associated account" do + custom_path = "account.custom_attr" DiscoursePluginRegistry.register_oauth2_basic_additional_json_path( custom_path, - Plugin::Instance.new + Plugin::Instance.new, ) stub_request(:get, SiteSetting.oauth2_user_json_url).to_return(response) @@ -126,7 +126,7 @@ describe OAuth2BasicAuthenticator do end end - describe 'avatar downloading' do + describe "avatar downloading" do before do SiteSetting.queue_jobs = true SiteSetting.oauth2_fetch_user_details = true @@ -136,61 +136,66 @@ describe OAuth2BasicAuthenticator do let(:job_klass) { Jobs::DownloadAvatarFromUrl } before do - png = Base64.decode64("R0lGODlhAQABALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//wBiZCH5BAEAAA8ALAAAAAABAAEAAAQC8EUAOw==") - stub_request(:get, "http://avatar.example.com/avatar.png").to_return(body: png, headers: { "Content-Type" => "image/png" }) + png = + Base64.decode64( + "R0lGODlhAQABALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//wBiZCH5BAEAAA8ALAAAAAABAAEAAAQC8EUAOw==", + ) + stub_request(:get, "http://avatar.example.com/avatar.png").to_return( + body: png, + headers: { + "Content-Type" => "image/png", + }, + ) end - it 'enqueues a download_avatar_from_url job for existing user' do + it "enqueues a download_avatar_from_url job for existing user" do authenticator.expects(:fetch_user_details).returns( email: user.email, - avatar: 'http://avatar.example.com/avatar.png' + avatar: "http://avatar.example.com/avatar.png", ) - expect { - authenticator.after_authenticate(auth) - }.to change { job_klass.jobs.count }.by(1) + expect { authenticator.after_authenticate(auth) }.to change { job_klass.jobs.count }.by(1) - job_args = job_klass.jobs.last['args'].first + job_args = job_klass.jobs.last["args"].first - expect(job_args['url']).to eq("http://avatar.example.com/avatar.png") - expect(job_args['user_id']).to eq(user.id) - expect(job_args['override_gravatar']).to eq(false) + expect(job_args["url"]).to eq("http://avatar.example.com/avatar.png") + expect(job_args["user_id"]).to eq(user.id) + expect(job_args["override_gravatar"]).to eq(false) end - it 'enqueues a download_avatar_from_url job for new user' do + it "enqueues a download_avatar_from_url job for new user" do authenticator.expects(:fetch_user_details).returns( email: "unknown@user.com", - avatar: 'http://avatar.example.com/avatar.png' + avatar: "http://avatar.example.com/avatar.png", ) auth_result = nil - expect { - auth_result = authenticator.after_authenticate(auth) - }.not_to change { job_klass.jobs.count } + expect { auth_result = authenticator.after_authenticate(auth) }.not_to change { + job_klass.jobs.count + } - expect { - authenticator.after_create_account(user, auth_result) - }.to change { job_klass.jobs.count }.by(1) + expect { authenticator.after_create_account(user, auth_result) }.to change { + job_klass.jobs.count + }.by(1) - job_args = job_klass.jobs.last['args'].first + job_args = job_klass.jobs.last["args"].first - expect(job_args['url']).to eq("http://avatar.example.com/avatar.png") - expect(job_args['user_id']).to eq(user.id) - expect(job_args['override_gravatar']).to eq(false) + expect(job_args["url"]).to eq("http://avatar.example.com/avatar.png") + expect(job_args["user_id"]).to eq(user.id) + expect(job_args["override_gravatar"]).to eq(false) end end - end - it 'can walk json' do + it "can walk json" do authenticator = OAuth2BasicAuthenticator.new json_string = '{"user":{"id":1234,"email":{"address":"test@example.com"}}}' - SiteSetting.oauth2_json_email_path = 'user.email.address' + SiteSetting.oauth2_json_email_path = "user.email.address" result = authenticator.json_walk({}, JSON.parse(json_string), :email) expect(result).to eq "test@example.com" end - it 'allows keys containing dots, if wrapped in quotes' do + it "allows keys containing dots, if wrapped in quotes" do authenticator = OAuth2BasicAuthenticator.new json_string = '{"www.example.com/uid": "myuid"}' SiteSetting.oauth2_json_user_id_path = '"www.example.com/uid"' @@ -199,7 +204,7 @@ describe OAuth2BasicAuthenticator do expect(result).to eq "myuid" end - it 'allows keys containing dots, if escaped' do + it "allows keys containing dots, if escaped" do authenticator = OAuth2BasicAuthenticator.new json_string = '{"www.example.com/uid": "myuid"}' SiteSetting.oauth2_json_user_id_path = 'www\.example\.com/uid' @@ -208,7 +213,7 @@ describe OAuth2BasicAuthenticator do expect(result).to eq "myuid" end - it 'allows keys containing literal backslashes, if escaped' do + it "allows keys containing literal backslashes, if escaped" do authenticator = OAuth2BasicAuthenticator.new # This 'single quoted heredoc' syntax means we don't have to escape backslashes in Ruby # What you see is exactly what the user would enter in the site settings @@ -222,107 +227,109 @@ describe OAuth2BasicAuthenticator do expect(result).to eq "myuid" end - it 'can walk json that contains an array' do + it "can walk json that contains an array" do authenticator = OAuth2BasicAuthenticator.new - json_string = '{"email":"test@example.com","identities":[{"user_id":"123456789","provider":"auth0","isSocial":false}]}' - SiteSetting.oauth2_json_user_id_path = 'identities.[].user_id' + json_string = + '{"email":"test@example.com","identities":[{"user_id":"123456789","provider":"auth0","isSocial":false}]}' + SiteSetting.oauth2_json_user_id_path = "identities.[].user_id" result = authenticator.json_walk({}, JSON.parse(json_string), :user_id) expect(result).to eq "123456789" end - it 'can walk json and handle an empty array' do + it "can walk json and handle an empty array" do authenticator = OAuth2BasicAuthenticator.new json_string = '{"email":"test@example.com","identities":[]}' - SiteSetting.oauth2_json_user_id_path = 'identities.[].user_id' + SiteSetting.oauth2_json_user_id_path = "identities.[].user_id" result = authenticator.json_walk({}, JSON.parse(json_string), :user_id) expect(result).to eq nil end - it 'can walk json and find values by index in an array' do + it "can walk json and find values by index in an array" do authenticator = OAuth2BasicAuthenticator.new json_string = '{"emails":[{"value":"test@example.com"},{"value":"test2@example.com"}]}' - SiteSetting.oauth2_json_email_path = 'emails[1].value' + SiteSetting.oauth2_json_email_path = "emails[1].value" result = authenticator.json_walk({}, JSON.parse(json_string), :email) expect(result).to eq "test2@example.com" end - it 'can walk json and download avatar' do + it "can walk json and download avatar" do authenticator = OAuth2BasicAuthenticator.new json_string = '{"user":{"avatar":"http://example.com/1.png"}}' - SiteSetting.oauth2_json_avatar_path = 'user.avatar' + SiteSetting.oauth2_json_avatar_path = "user.avatar" result = authenticator.json_walk({}, JSON.parse(json_string), :avatar) - expect(result).to eq 'http://example.com/1.png' + expect(result).to eq "http://example.com/1.png" end - describe 'token_callback' do + describe "token_callback" do let(:user) { Fabricate(:user) } let(:strategy) { OmniAuth::Strategies::Oauth2Basic.new({}) } let(:authenticator) { OAuth2BasicAuthenticator.new } let(:auth) do OmniAuth::AuthHash.new( - 'provider' => 'oauth2_basic', - 'credentials' => { - 'token' => 'token' + "provider" => "oauth2_basic", + "credentials" => { + "token" => "token", }, - 'uid' => 'e028b1b918853eca7fba208a9d7e9d29a6e93c57', - 'info' => { - "name" => 'Sammy the Shark', - "email" => 'sammy@digitalocean.com' + "uid" => "e028b1b918853eca7fba208a9d7e9d29a6e93c57", + "info" => { + "name" => "Sammy the Shark", + "email" => "sammy@digitalocean.com", + }, + "extra" => { }, - 'extra' => {} ) end let(:access_token) do - { "params" => - { "info" => - { + { + "params" => { + "info" => { "name" => "Sammy the Shark", "email" => "sammy@digitalocean.com", - "uuid" => "e028b1b918853eca7fba208a9d7e9d29a6e93c57" - } - } + "uuid" => "e028b1b918853eca7fba208a9d7e9d29a6e93c57", + }, + }, } end before(:each) do - SiteSetting.oauth2_callback_user_id_path = 'params.info.uuid' - SiteSetting.oauth2_callback_user_info_paths = 'name:params.info.name|email:params.info.email' + SiteSetting.oauth2_callback_user_id_path = "params.info.uuid" + SiteSetting.oauth2_callback_user_info_paths = "name:params.info.name|email:params.info.email" end - it 'can retrieve user id from access token callback' do + it "can retrieve user id from access token callback" do strategy.stubs(:access_token).returns(access_token) - expect(strategy.uid).to eq 'e028b1b918853eca7fba208a9d7e9d29a6e93c57' + expect(strategy.uid).to eq "e028b1b918853eca7fba208a9d7e9d29a6e93c57" end - it 'can retrieve user properties from access token callback' do + it "can retrieve user properties from access token callback" do strategy.stubs(:access_token).returns(access_token) - expect(strategy.info['name']).to eq 'Sammy the Shark' - expect(strategy.info['email']).to eq 'sammy@digitalocean.com' + expect(strategy.info["name"]).to eq "Sammy the Shark" + expect(strategy.info["email"]).to eq "sammy@digitalocean.com" end - it 'does apply user properties from access token callback in after_authenticate' do + it "does apply user properties from access token callback in after_authenticate" do SiteSetting.oauth2_fetch_user_details = true - authenticator.stubs(:fetch_user_details).returns(email: 'sammy@digitalocean.com') + authenticator.stubs(:fetch_user_details).returns(email: "sammy@digitalocean.com") result = authenticator.after_authenticate(auth) - expect(result.extra_data[:uid]).to eq 'e028b1b918853eca7fba208a9d7e9d29a6e93c57' - expect(result.name).to eq 'Sammy the Shark' - expect(result.email).to eq 'sammy@digitalocean.com' + expect(result.extra_data[:uid]).to eq "e028b1b918853eca7fba208a9d7e9d29a6e93c57" + expect(result.name).to eq "Sammy the Shark" + expect(result.email).to eq "sammy@digitalocean.com" end - it 'does work if user details are not fetched' do + it "does work if user details are not fetched" do SiteSetting.oauth2_fetch_user_details = false result = authenticator.after_authenticate(auth) - expect(result.extra_data[:uid]).to eq 'e028b1b918853eca7fba208a9d7e9d29a6e93c57' - expect(result.name).to eq 'Sammy the Shark' - expect(result.email).to eq 'sammy@digitalocean.com' + expect(result.extra_data[:uid]).to eq "e028b1b918853eca7fba208a9d7e9d29a6e93c57" + expect(result.name).to eq "Sammy the Shark" + expect(result.email).to eq "sammy@digitalocean.com" end end end