DEV: Introduce syntax_tree for ruby formatting (#75)
This commit is contained in:
parent
4a5259d81e
commit
ccf9d5d32c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
inherit_gem:
|
||||
rubocop-discourse: default.yml
|
||||
rubocop-discourse: stree-compat.yml
|
||||
|
|
5
Gemfile
5
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
|
||||
|
|
|
@ -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
|
||||
|
|
166
plugin.rb
166
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__,
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue