FEATURE: Allow invites redemption with Omniauth providers.

This commit is contained in:
Alan Guo Xiang Tan
2021-03-02 15:13:04 +08:00
parent ebe4896e48
commit ce04db8610
21 changed files with 621 additions and 139 deletions

View File

@@ -374,6 +374,97 @@ describe InvitesController do
expect(invite.redeemed?).to be_truthy
end
it 'returns the right response when local login is disabled and no external auth is configured' do
SiteSetting.enable_local_logins = false
put "/invites/show/#{invite.invite_key}.json"
expect(response.status).to eq(404)
end
it 'returns the right response when DiscourseConnect is enabled' do
invite
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
SiteSetting.enable_discourse_connect = true
put "/invites/show/#{invite.invite_key}.json"
expect(response.status).to eq(404)
end
describe 'with authentication session' do
let(:authenticated_email) { "foobar@example.com" }
before do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:google_oauth2] = OmniAuth::AuthHash.new(
provider: 'google_oauth2',
uid: '12345',
info: OmniAuth::AuthHash::InfoHash.new(
email: authenticated_email,
name: 'First Last'
),
extra: {
raw_info: OmniAuth::AuthHash.new(
email_verified: true,
email: authenticated_email,
family_name: "Last",
given_name: "First",
gender: "male",
name: "First Last",
)
},
)
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:google_oauth2]
SiteSetting.enable_google_oauth2_logins = true
get "/auth/google_oauth2/callback.json"
expect(response.status).to eq(302)
end
after do
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:google_oauth2] = nil
OmniAuth.config.test_mode = false
end
it 'should associate the invited user with authenticator records' do
invite.update!(email: authenticated_email)
SiteSetting.auth_overrides_name = true
expect do
put "/invites/show/#{invite.invite_key}.json",
params: { name: 'somename' }
expect(response.status).to eq(200)
end.to change { User.with_email(authenticated_email).exists? }.to(true)
user = User.find_by_email(authenticated_email)
expect(user.name).to eq('First Last')
expect(user.user_associated_accounts.first.provider_name)
.to eq("google_oauth2")
end
it 'returns the right response even if local logins has been disabled' do
SiteSetting.enable_local_logins = false
invite.update!(email: authenticated_email)
put "/invites/show/#{invite.invite_key}.json"
expect(response.status).to eq(200)
end
it 'returns the right response if authenticated email does not match invite email' do
put "/invites/show/#{invite.invite_key}.json"
expect(response.status).to eq(412)
end
end
context 'when redeem returns a user' do
fab!(:user) { Fabricate(:coding_horror) }
@@ -447,27 +538,6 @@ describe InvitesController do
expect(Jobs::InvitePasswordInstructionsEmail.jobs.size).to eq(1)
expect(Jobs::CriticalUserEmail.jobs.size).to eq(0)
end
it "does not send password reset email if sso is enabled" do
invite # create the invite before enabling SSO
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
SiteSetting.enable_discourse_connect = true
put "/invites/show/#{invite.invite_key}.json"
expect(response.status).to eq(200)
expect(Jobs::InvitePasswordInstructionsEmail.jobs.size).to eq(0)
expect(Jobs::CriticalUserEmail.jobs.size).to eq(0)
end
it "does not send password reset email if local login is disabled" do
invite # create the invite before enabling SSO
SiteSetting.enable_local_logins = false
put "/invites/show/#{invite.invite_key}.json"
expect(response.status).to eq(200)
expect(Jobs::InvitePasswordInstructionsEmail.jobs.size).to eq(0)
expect(Jobs::CriticalUserEmail.jobs.size).to eq(0)
end
end
context "with password" do

View File

@@ -12,6 +12,7 @@ RSpec.describe Users::OmniauthCallbacksController do
after do
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:google_oauth2] = nil
Rails.application.env_config["omniauth.origin"] = nil
OmniAuth.config.test_mode = false
end
@@ -221,6 +222,48 @@ RSpec.describe Users::OmniauthCallbacksController do
data = JSON.parse(cookies[:authentication_data])
expect(data["destination_url"]).to eq(destination_url)
end
describe 'when site is invite_only' do
before do
SiteSetting.invite_only = true
end
it 'should return the right response without any origin' do
get "/auth/google_oauth2/callback.json"
expect(response.status).to eq(302)
data = JSON.parse(response.cookies["authentication_data"])
expect(data["requires_invite"]).to eq(true)
end
it 'returns the right response for an invalid origin' do
Rails.application.env_config["omniauth.origin"] = "/invitesinvites"
get "/auth/google_oauth2/callback.json"
expect(response.status).to eq(302)
end
it 'should return the right response when origin is invites page' do
origin = Rails.application.routes.url_helpers.invite_url(
Fabricate(:invite).invite_key,
host: Discourse.base_url
)
Rails.application.env_config["omniauth.origin"] = origin
get "/auth/google_oauth2/callback.json"
expect(response.status).to eq(302)
expect(response).to redirect_to(origin)
data = JSON.parse(response.cookies["authentication_data"])
expect(data["requires_invite"]).to eq(nil)
end
end
end
describe 'when user has been verified' do

View File

@@ -1755,20 +1755,24 @@ describe UsersController do
expect(response.status).to eq(403)
end
end
end
context 'when local logins are disabled' do
it 'explains why invites are disabled to staff users' do
SiteSetting.enable_local_logins = false
inviter = sign_in(Fabricate(:admin))
Fabricate(:invite, invited_by: inviter, email: nil, max_redemptions_allowed: 5, expires_at: 1.month.from_now, emailed_status: Invite.emailed_status_types[:not_required])
context 'when DiscourseConnect has been enabled' do
before do
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
SiteSetting.enable_discourse_connect = true
end
get "/u/#{inviter.username}/invited/pending.json"
expect(response.status).to eq(200)
it 'explains why invites are disabled to staff users' do
inviter = sign_in(Fabricate(:admin))
Fabricate(:invite, invited_by: inviter, email: nil, max_redemptions_allowed: 5, expires_at: 1.month.from_now, emailed_status: Invite.emailed_status_types[:not_required])
expect(response.parsed_body['error']).to include(I18n.t(
'invite.disabled_errors.local_logins_disabled'
))
end
get "/u/#{inviter.username}/invited/pending.json"
expect(response.status).to eq(200)
expect(response.parsed_body['error']).to include(I18n.t(
'invite.disabled_errors.discourse_connect_enabled'
))
end
end