[Email/Password Authentication] Allow Admins to enable email/password login (#10745)

* Implement Admins ability to allow email login

* Write specs for admin allow email login

* Fix specs causing builds to fail

* Fix spec causing builds to fail

* Use dummyimage.com for spec images

Co-authored-by: Josh Puetz <joshpuetz@gmail.com>

* Use dummyimage.com

* refactor setting of SiteConfig attributes

* Address PR review comments

* fix indentation

* Use "allow to receive and return" approach for other specs

Co-authored-by: Josh Puetz <joshpuetz@gmail.com>
This commit is contained in:
Arit Amana 2020-10-12 12:54:35 -04:00 committed by GitHub
parent e42b6d6b46
commit f4bd1df21c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 84 additions and 39 deletions

View file

@ -57,6 +57,7 @@ module Admin
facebook_secret
invite_only_mode
allow_email_password_registration
allow_email_password_login
primary_brand_color_hex
spam_trigger_terms
recaptcha_site_key

View file

@ -5,6 +5,10 @@ module Constants
description: "Can users sign up with only email and password?",
placeholder: ""
},
allow_email_password_login: {
description: "Can users login with only email and password?",
placeholder: ""
},
authentication_providers: {
description: "How can users sign in?",
placeholder: ""

View file

@ -22,6 +22,7 @@ class SiteConfig < RailsSettings::Base
# Authentication
field :allow_email_password_registration, type: :boolean, default: false
field :allow_email_password_login, type: :boolean, default: false
field :authentication_providers, type: :array, default: proc { Authentication::Providers.available }
field :invite_only_mode, type: :boolean, default: false
field :twitter_key, type: :string, default: ApplicationConfig["TWITTER_KEY"]

View file

@ -126,6 +126,11 @@
<%= f.check_box :allow_email_password_registration, checked: SiteConfig.allow_email_password_registration %>
<div class="alert alert-info"><%= Constants::SiteConfig::DETAILS[:allow_email_password_registration][:description] %></div>
</div>
<div class="form-group">
<%= admin_config_label :allow_email_password_login %>
<%= f.check_box :allow_email_password_login, checked: SiteConfig.allow_email_password_login %>
<div class="alert alert-info"><%= Constants::SiteConfig::DETAILS[:allow_email_password_login][:description] %></div>
</div>
<div class="form-group">
<%= admin_config_label :authentication_providers %>
<%= select_tag "site_config[authentication_providers]",

View file

@ -26,40 +26,14 @@
</div>
<% else %>
<div class="registration__actions-email" id="sign-in-password-form">
<%# if there are no SSO auths enabled, we don't ask the user if they have a password %>
<% if authentication_enabled_providers.any? %>
<% if SiteConfig.allow_email_password_login %>
<div class="registration__hr">
<span class="registration__hr-label">
Have a password? Continue with your email address
</span>
</div>
<%= render partial: "shared/authentication/email_login_form" %>
<% end %>
<%= form_for(User.new, as: :user, url: session_path(:user)) do |f| %>
<div class="crayons-field mb-3">
<%= f.label :email, class: "crayons-field__label" %>
<%= f.email_field :email, autocomplete: "email", class: "crayons-textfield" %>
</div>
<div class="crayons-field mb-3">
<%= f.label :password, class: "crayons-field__label" %>
<%= f.password_field :password, autocomplete: "current-password", class: "crayons-textfield" %>
</div>
<div class="crayons-field crayons-field--checkbox inline-flex flex-row items-center">
<%= f.check_box :remember_me, class: "crayons-checkbox" %>
<%= f.label :remember_me, class: "crayons-field__label fw-normal" %>
</div>
<div class="actions pt-3">
<%= f.submit "Continue", class: "crayons-btn crayons-btn--l w-100" %>
</div>
<% end %>
<p class="pt-6 fs-s align-center">
<a href="<%= new_password_path(:user) %>">
I forgot my password
</a>
</p>
</div>
<% end %>
</div>

View file

@ -0,0 +1,25 @@
<%= form_for(User.new, as: :user, url: session_path(:user)) do |f| %>
<div class="crayons-field mb-3">
<%= f.label :email, class: "crayons-field__label" %>
<%= f.email_field :email, autocomplete: "email", class: "crayons-textfield" %>
</div>
<div class="crayons-field mb-3">
<%= f.label :password, class: "crayons-field__label" %>
<%= f.password_field :password, autocomplete: "current-password", class: "crayons-textfield" %>
</div>
<div class="crayons-field crayons-field--checkbox inline-flex flex-row items-center">
<%= f.check_box :remember_me, class: "crayons-checkbox" %>
<%= f.label :remember_me, class: "crayons-field__label fw-normal" %>
</div>
<div class="actions pt-3">
<%= f.submit "Continue", class: "crayons-btn crayons-btn--l w-100" %>
</div>
<% end %>
<p class="pt-6 fs-s align-center">
<a href="<%= new_password_path(:user) %>">
I forgot my password
</a>
</p>

6
spec/fixtures/files/300x100.svg vendored Normal file
View file

@ -0,0 +1,6 @@
<svg width="300" height="100" xmlns="http://www.w3.org/2000/svg">
<path fill="#dedede" stroke="#555" stroke-width="2" d="M2 2h296v96H2z"/>
<text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555">
300×100
</text>
</svg>

After

Width:  |  Height:  |  Size: 308 B

View file

@ -7,6 +7,18 @@ RSpec.describe "Editor", type: :request do
get new_path
expect(response).to have_http_status(:ok)
end
end
context "when email login is allowed in /admin/config" do
before do
allow(SiteConfig).to receive(:allow_email_password_login).and_return(true)
end
it "asks the non logged in user to sign in, with email signin enabled" do
get new_path
expect(response.body).to include("Email")
expect(response.body).to include("Password")
end
end

View file

@ -15,27 +15,36 @@ RSpec.describe "Registrations", type: :request do
end
end
it "shows the sign in text for password based authentication" do
get sign_up_path
expect(response.body).to include("Have a password? Continue with your email address")
end
it "does not show the password based authentication hint if there are no single sign in options enabled" do
it "only shows the single sign on options if they are present" do
allow(Authentication::Providers).to receive(:enabled).and_return([])
get sign_up_path
expect(response.body).not_to include("Have a password? Continue with your email address")
end
end
it "only shows the single sign on options if they are present" do
allow(Authentication::Providers).to receive(:enabled).and_return([])
context "when email login is enabled in /admin/config" do
before do
allow(SiteConfig).to receive(:allow_email_password_login).and_return(true)
end
it "shows the sign in text for password based authentication" do
get sign_up_path
expect(response.body).to include("Password")
expect(response.body).not_to include("Continue with")
expect(response.body).to include("Have a password? Continue with your email address")
end
end
context "when email login is disabled in /admin/config" do
before do
allow(SiteConfig).to receive(:allow_email_password_login).and_return(false)
end
it "does not show the sign in text for password based authentication" do
get sign_up_path
expect(response.body).not_to include("Have a password? Continue with your email address")
end
end

View file

@ -4,8 +4,15 @@ RSpec.describe "Editing with an editor", type: :system, js: true do
let(:template) { file_fixture("article_published.txt").read }
let(:user) { create(:user) }
let(:article) { create(:article, user: user, body_markdown: template) }
let(:svg_image) { file_fixture("300x100.svg").read }
before do
allow(SiteConfig).to receive(:main_social_image).and_return("https://dummyimage.com/800x600.jpg")
allow(SiteConfig).to receive(:logo_png).and_return("https://dummyimage.com/800x600.png")
allow(SiteConfig).to receive(:mascot_image_url).and_return("https://dummyimage.com/800x600.jpg")
allow(SiteConfig).to receive(:suggested_tags).and_return("coding, beginners")
allow(SiteConfig).to receive(:suggested_users).and_return("romagueramica")
allow(SiteConfig).to receive(:logo_svg).and_return(svg_image)
sign_in user
end

View file

@ -11,6 +11,7 @@ RSpec.describe "Authenticating with a password" do
let!(:user) { create(:user, password: password, password_confirmation: password) }
before do
allow(SiteConfig).to receive(:allow_email_password_login).and_return(true)
visit sign_up_path
end