[Team Email Login] Refactor the Email Authentication flow (#11090)
* Hooked "Enable" button to hidden checkbox * Hooked "Close" button to close email settings and show "Enable/Edit" button * Additional hookups * Start building generalized Modal blocks * Everything hooked up except styling and a few Qs * last of the hookups; ensure logic flow * clean up * specs to cover email auth refactor * Fix bug surfaced by Vaidehi * Incorporate PR feedback * prevent email auth disable if invite-only-mode * adjust emailAuthModal body text * Sundry improvements * Last-mile tweaks * Trying to get 3rd party auth deselect to work * delete unnecssary function * remove superfluous comment * Move inline styling into CSS file * Incorporate PR feedback * Incorporate more PR feedback * Make Confirm btn intent clearer * Add TODO comment
This commit is contained in:
parent
fc22e2c4ae
commit
1912ffdc46
9 changed files with 248 additions and 58 deletions
|
|
@ -125,3 +125,15 @@ label {
|
|||
flex-direction: column;
|
||||
gap: var(--su-4);
|
||||
}
|
||||
|
||||
.admin-config-checkmark {
|
||||
width: var(--su-4);
|
||||
height: var(--su-4);
|
||||
background-color: var(--accent-success);
|
||||
border-radius: 100%;
|
||||
color: var(--base-inverted);
|
||||
}
|
||||
|
||||
.cursor-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,8 +118,7 @@ module Admin
|
|||
facebook_key
|
||||
facebook_secret
|
||||
invite_only_mode
|
||||
allow_email_password_registration
|
||||
allow_email_password_login
|
||||
allow_both_email_signup_and_login
|
||||
require_captcha_for_email_password_registration
|
||||
primary_brand_color_hex
|
||||
spam_trigger_terms
|
||||
|
|
@ -153,6 +152,8 @@ module Admin
|
|||
end
|
||||
end
|
||||
|
||||
toggle_email_password_authentication
|
||||
|
||||
redirect_to admin_config_path, notice: "Site configuration was successfully updated."
|
||||
end
|
||||
|
||||
|
|
@ -211,6 +212,17 @@ module Admin
|
|||
config[:credit_prices_in_cents]&.transform_values!(&:to_i)
|
||||
end
|
||||
|
||||
def toggle_email_password_authentication
|
||||
if SiteConfig.allow_both_email_signup_and_login
|
||||
SiteConfig.allow_email_password_registration = true
|
||||
SiteConfig.allow_email_password_login = true
|
||||
else
|
||||
SiteConfig.allow_email_password_registration = false
|
||||
SiteConfig.allow_email_password_login = false
|
||||
SiteConfig.invite_only_mode = false
|
||||
end
|
||||
end
|
||||
|
||||
# Validations
|
||||
def brand_contrast_too_low
|
||||
hex = params.dig(:site_config, :primary_brand_color_hex)
|
||||
|
|
|
|||
|
|
@ -32,4 +32,24 @@ module AuthenticationHelper
|
|||
def waiting_on_first_user?
|
||||
SiteConfig.waiting_on_first_user
|
||||
end
|
||||
|
||||
def disable_email_tooltip_class
|
||||
SiteConfig.invite_only_mode || authentication_enabled_providers.none? ? "crayons-tooltip" : ""
|
||||
end
|
||||
|
||||
def disable_email_tooltip_content
|
||||
SiteConfig.invite_only_mode || authentication_enabled_providers.none? ? disable_email_auth_tooltip_text : ""
|
||||
end
|
||||
|
||||
def disable_button_class
|
||||
SiteConfig.invite_only_mode || authentication_enabled_providers.none? ? "disabled" : ""
|
||||
end
|
||||
|
||||
def disable_email_auth_tooltip_text
|
||||
if SiteConfig.invite_only_mode
|
||||
"You cannot do this until you disable Invite Only Mode"
|
||||
elsif authentication_enabled_providers.none?
|
||||
"You cannot do this until you enable at least one other registration option"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,63 @@
|
|||
import { Controller } from 'stimulus';
|
||||
|
||||
const recaptchaFields = document.querySelector('#recaptchaContainer');
|
||||
const emailSigninAndLoginCheckbox = document.querySelector(
|
||||
'#email-signup-and-login-checkbox',
|
||||
);
|
||||
const emailAuthSettingsSection = document.querySelector(
|
||||
'#email-auth-settings-section',
|
||||
);
|
||||
const modalAnchor = document.querySelector('.admin-config-modal-anchor');
|
||||
const emailAuthModalTitle = 'Disable email address registration';
|
||||
// TODO: Remove the sentence "You must update site config to save this action!"
|
||||
// once we build more robust flow for Admin/Config
|
||||
const emailAuthModalBody =
|
||||
'<p>If you disable email address as a registration option, people cannot create an account with their email address.</p><br /><p>However, people who have already created an account using their email address can continue to login.</p><br /><p><strong>You must update site config to save this action!</strong></p>';
|
||||
|
||||
const adminConfigModal = (
|
||||
title,
|
||||
body,
|
||||
confirmBtnText,
|
||||
confirmBtnAction,
|
||||
cancelBtnText,
|
||||
cancelBtnAction,
|
||||
) => `
|
||||
<div class="crayons-modal crayons-modal--s absolute">
|
||||
<div class="crayons-modal__box">
|
||||
<header class="crayons-modal__box__header">
|
||||
<p class="fw-bold fs-l">${title}</p>
|
||||
<button type="button" class="crayons-btn crayons-btn--icon crayons-btn--ghost" data-action="click->config#closeAdminConfigModal">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" class="crayons-icon" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636l4.95 4.95z" />
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
<div class="crayons-modal__box__body">
|
||||
${body}
|
||||
<div class="mt-6">
|
||||
<button
|
||||
class="crayons-btn crayons-btn--danger"
|
||||
data-action="click->config#${confirmBtnAction}">
|
||||
${confirmBtnText}
|
||||
</button>
|
||||
<button
|
||||
class="crayons-btn crayons-btn--secondary"
|
||||
data-action="click->config#${cancelBtnAction}">
|
||||
${cancelBtnText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="crayons-modal__overlay"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default class ConfigController extends Controller {
|
||||
static targets = [
|
||||
'authenticationProviders',
|
||||
'collectiveNoun',
|
||||
'emailAuthSettingsBtn',
|
||||
'inviteOnlyMode',
|
||||
'requireCaptchaForEmailPasswordRegistration',
|
||||
];
|
||||
|
||||
|
|
@ -29,9 +81,59 @@ export default class ConfigController extends Controller {
|
|||
|
||||
toggleGoogleRecaptchaFields() {
|
||||
if (this.requireCaptchaForEmailPasswordRegistrationTarget.checked) {
|
||||
recaptchaFields.classList.remove('collapse');
|
||||
recaptchaFields.classList.remove('hidden');
|
||||
} else {
|
||||
recaptchaFields.classList.add('collapse');
|
||||
recaptchaFields.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
enableOrEditEmailAuthSettings() {
|
||||
event.preventDefault();
|
||||
if (this.emailAuthSettingsBtnTarget.dataset.buttonText === 'enable') {
|
||||
emailSigninAndLoginCheckbox.checked = true;
|
||||
}
|
||||
this.emailAuthSettingsBtnTarget.classList.add('hidden');
|
||||
emailAuthSettingsSection.classList.remove('hidden');
|
||||
}
|
||||
|
||||
hideEmailAuthSettings() {
|
||||
event.preventDefault();
|
||||
this.emailAuthSettingsBtnTarget.classList.remove('hidden');
|
||||
emailAuthSettingsSection.classList.add('hidden');
|
||||
}
|
||||
|
||||
activateEmailAuthModal() {
|
||||
event.preventDefault();
|
||||
modalAnchor.innerHTML = adminConfigModal(
|
||||
emailAuthModalTitle,
|
||||
emailAuthModalBody,
|
||||
'Confirm',
|
||||
'disableEmailAuthFromModal',
|
||||
'Cancel',
|
||||
'closeAdminConfigModal',
|
||||
);
|
||||
if (document.querySelector('.crayons-modal')) {
|
||||
window.scrollTo(0, 0);
|
||||
document.body.style.height = '100vh';
|
||||
document.body.style.overflowY = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
closeAdminConfigModal() {
|
||||
modalAnchor.innerHTML = '';
|
||||
document.body.style.height = 'inherit';
|
||||
document.body.style.overflowY = 'inherit';
|
||||
}
|
||||
|
||||
disableEmailAuthFromModal() {
|
||||
event.preventDefault();
|
||||
emailSigninAndLoginCheckbox.checked = false;
|
||||
this.closeAdminConfigModal();
|
||||
}
|
||||
|
||||
disableEmailAuth() {
|
||||
event.preventDefault();
|
||||
emailSigninAndLoginCheckbox.checked = false;
|
||||
this.hideEmailAuthSettings();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,6 @@ module Constants
|
|||
SVG_PLACEHOLDER = "<svg ...></svg>".freeze
|
||||
|
||||
DETAILS = {
|
||||
allow_email_password_registration: {
|
||||
description: "People can sign up using their email and password",
|
||||
placeholder: ""
|
||||
},
|
||||
allow_email_password_login: {
|
||||
description: "People can login using their email and password",
|
||||
placeholder: ""
|
||||
},
|
||||
require_captcha_for_email_password_registration: {
|
||||
description: "People will be required to fill out a captcha when
|
||||
they're creating a new account in your community",
|
||||
|
|
@ -155,7 +147,7 @@ module Constants
|
|||
placeholder: "0"
|
||||
},
|
||||
invite_only_mode: {
|
||||
description: "Only users invited by email can join this community.",
|
||||
description: "Only users invited by email can join this community. To use this, you must enable email address registration.",
|
||||
placeholder: ""
|
||||
},
|
||||
jobs_url: {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@ class SiteConfig < RailsSettings::Base
|
|||
field :video_encoder_key, type: :string
|
||||
|
||||
# Authentication
|
||||
field :allow_email_password_registration, type: :boolean, default: false
|
||||
field :allow_email_password_registration, type: :boolean, default: true
|
||||
field :allow_email_password_login, type: :boolean, default: true
|
||||
field :allow_both_email_signup_and_login, type: :boolean, default: true
|
||||
field :require_captcha_for_email_password_registration, type: :boolean, default: false
|
||||
field :authentication_providers, type: :array, default: proc { Authentication::Providers.available }
|
||||
field :invite_only_mode, type: :boolean, default: false
|
||||
|
|
|
|||
|
|
@ -141,7 +141,11 @@
|
|||
</h3>
|
||||
<div class="form-group">
|
||||
<div class="crayons-field--checkbox">
|
||||
<%= f.check_box :invite_only_mode, checked: SiteConfig.invite_only_mode, data: { action: "config#disableTargetField", disable_target: "authenticationProviders" }, class: "crayons-checkbox" %>
|
||||
<%= f.check_box :invite_only_mode,
|
||||
checked: SiteConfig.invite_only_mode,
|
||||
disabled: !SiteConfig.allow_both_email_signup_and_login,
|
||||
data: { action: "config#disableAuthenticationOptions", target: "config.inviteOnlyMode" },
|
||||
class: "crayons-checkbox #{!SiteConfig.allow_both_email_signup_and_login ? 'cursor-disabled' : ''}" %>
|
||||
<div class="mt-0">
|
||||
<%= admin_config_label :invite_only_mode %>
|
||||
<%= admin_config_description Constants::SiteConfig::DETAILS[:invite_only_mode][:description] %>
|
||||
|
|
@ -150,55 +154,45 @@
|
|||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="crayons-subtitle-3 mb-3">
|
||||
Authentication methods
|
||||
<h3 class="crayons-subtitle-3 mb-1">
|
||||
Registration options
|
||||
</h3>
|
||||
<div class="form-group">
|
||||
<%= admin_config_label :authentication_providers %>
|
||||
<p class="crayons-field__description">
|
||||
<%= Constants::SiteConfig::DETAILS[:authentication_providers][:description] %>
|
||||
</p>
|
||||
<%= select_tag "site_config[authentication_providers]",
|
||||
options_from_collection_for_select(
|
||||
authentication_available_providers,
|
||||
:provider_name,
|
||||
:official_name,
|
||||
authentication_enabled_providers.map(&:provider_name),
|
||||
),
|
||||
multiple: true,
|
||||
class: "form-control selectpicker",
|
||||
data: { target: "config.authenticationProviders" } %>
|
||||
</div>
|
||||
<p class="crayons-field__description mb-6">
|
||||
How can people create an account on your community?
|
||||
</p>
|
||||
|
||||
<section class="config-authentication__item">
|
||||
<figure class="config-authentication__item--icon">
|
||||
<%= inline_svg_tag("email.svg", class: "crayons-icon", aria: true, title: "Twitter logo") %>
|
||||
<%= inline_svg_tag("email.svg", class: "crayons-icon", aria: true, title: "Email icon") %>
|
||||
</figure>
|
||||
<div class="config-authentication__item--container">
|
||||
<div class="config-authentication__item--label">
|
||||
<p class="fw-medium">
|
||||
Email address and password
|
||||
</p>
|
||||
<div class="config-authentication__item flex items-baseline justify-between">
|
||||
<div>
|
||||
<p class="config-authentication__item--label fw-medium <%= SiteConfig.allow_both_email_signup_and_login ? "pb-0" : "" %>">
|
||||
Email address
|
||||
</p>
|
||||
<% if SiteConfig.allow_both_email_signup_and_login %>
|
||||
<div class="mb-5 flex items-center">
|
||||
<%= inline_svg_tag("checkmark.svg", aria: true, class: "crayons-icon admin-config-checkmark", title: "Checkmark") %>
|
||||
<small class="crayons-field__description ml-1">Enabled</small>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<button
|
||||
class="crayons-btn crayons-btn--secondary"
|
||||
data-button-text="<%= SiteConfig.allow_both_email_signup_and_login ? "edit" : "enable" %>"
|
||||
data-target="config.emailAuthSettingsBtn"
|
||||
data-action="click->config#enableOrEditEmailAuthSettings">
|
||||
<%= SiteConfig.allow_both_email_signup_and_login ? "Edit" : "Enable" %>
|
||||
</button>
|
||||
</div>
|
||||
<div class="config-authentication__item--body">
|
||||
<div id="email-auth-settings-section" class="config-authentication__item--body hidden">
|
||||
<fieldset class="config-authentication-form">
|
||||
<div class="crayons-field--checkbox">
|
||||
<%= f.check_box :allow_email_password_registration, checked: SiteConfig.allow_email_password_registration, class: "crayons-checkbox" %>
|
||||
<div>
|
||||
<%= admin_config_label :allow_email_password_registration %>
|
||||
<p class="crayons-field__description">
|
||||
<%= Constants::SiteConfig::DETAILS[:allow_email_password_registration][:description] %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="crayons-field--checkbox">
|
||||
<%= f.check_box :allow_email_password_login, checked: SiteConfig.allow_email_password_login, class: "crayons-checkbox" %>
|
||||
<div>
|
||||
<%= admin_config_label :allow_email_password_login %>
|
||||
<p class="crayons-field__description">
|
||||
<%= Constants::SiteConfig::DETAILS[:allow_email_password_login][:description] %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="crayons-field--checkbox hidden">
|
||||
<%= f.check_box :allow_both_email_signup_and_login,
|
||||
checked: SiteConfig.allow_both_email_signup_and_login,
|
||||
id: "email-signup-and-login-checkbox",
|
||||
class: "crayons-checkbox" %>
|
||||
</div>
|
||||
<div class="crayons-field--checkbox">
|
||||
<%= f.check_box :require_captcha_for_email_password_registration,
|
||||
|
|
@ -212,7 +206,7 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="recaptchaContainer" class="<%= SiteConfig.require_captcha_for_email_password_registration ? "" : "collapse" %> ml-7" aria-labelledby="recaptchaContainer">
|
||||
<div id="recaptchaContainer" class="<%= SiteConfig.require_captcha_for_email_password_registration ? "" : "hidden" %> ml-7" aria-labelledby="recaptchaContainer">
|
||||
<div class="form-group">
|
||||
<%= admin_config_label :recaptcha_site_key, "Google reCAPTCHA site key" %>
|
||||
<p class="crayons-field__description mb-1">
|
||||
|
|
@ -234,11 +228,52 @@
|
|||
placeholder: Constants::SiteConfig::DETAILS[:recaptcha_secret_key][:placeholder] %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<% if SiteConfig.allow_both_email_signup_and_login %>
|
||||
<button
|
||||
class="crayons-btn crayons-btn--danger <%= disable_email_tooltip_class %>"
|
||||
data-action="click->config#activateEmailAuthModal"
|
||||
data-tooltip="<%= disable_email_tooltip_content %>"
|
||||
<%= disable_button_class %>>
|
||||
Disable
|
||||
</button>
|
||||
<% end %>
|
||||
<% if SiteConfig.allow_both_email_signup_and_login %>
|
||||
<button
|
||||
class="crayons-btn crayons-btn--secondary"
|
||||
data-action="click->config#hideEmailAuthSettings">
|
||||
Close
|
||||
</button>
|
||||
<% else %>
|
||||
<button
|
||||
class="crayons-btn crayons-btn--secondary"
|
||||
data-action="click->config#disableEmailAuth">
|
||||
Undo
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="form-group">
|
||||
<%= admin_config_label :authentication_providers %>
|
||||
<p class="crayons-field__description">
|
||||
<%= Constants::SiteConfig::DETAILS[:authentication_providers][:description] %>
|
||||
</p>
|
||||
<%= select_tag "site_config[authentication_providers]",
|
||||
options_from_collection_for_select(
|
||||
authentication_available_providers,
|
||||
:provider_name,
|
||||
:official_name,
|
||||
authentication_enabled_providers.map(&:provider_name),
|
||||
),
|
||||
multiple: true,
|
||||
class: "form-control selectpicker",
|
||||
data: { target: "config.authenticationProviders" } %>
|
||||
</div>
|
||||
|
||||
<section class="config-authentication__item">
|
||||
<figure class="config-authentication__item--icon">
|
||||
<%= inline_svg_tag("twitter.svg", class: "crayons-icon", aria: true, title: "Twitter logo") %>
|
||||
|
|
@ -1338,4 +1373,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-config-modal-anchor"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<%= params[:state] == "new-user" ? "Sign up" : "Continue" %> with <%= provider.official_name %>
|
||||
</a>
|
||||
<% end %>
|
||||
<% if params[:state] == "new-user" && SiteConfig.allow_email_password_registration %>
|
||||
<% if params[:state] == "new-user" && SiteConfig.allow_email_password_registration && !SiteConfig.invite_only_mode %>
|
||||
<%= link_to "#{inline_svg_tag('email.svg', aria: true, class: 'crayons-icon', title: 'email')}Sign up with Email".html_safe,
|
||||
request.params.merge(state: "email_signup").except("i"),
|
||||
class: "crayons-btn crayons-btn--l crayons-btn--brand-email crayons-btn--icon-left whitespace-nowrap",
|
||||
|
|
|
|||
|
|
@ -87,6 +87,21 @@ RSpec.describe "/admin/config", type: :request do
|
|||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.authentication_providers).to eq([provider])
|
||||
end
|
||||
|
||||
it "enables email authentication" do
|
||||
post "/admin/config", params: { site_config: { allow_both_email_signup_and_login: true },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.allow_email_password_registration).to be(true)
|
||||
expect(SiteConfig.allow_email_password_login).to be(true)
|
||||
end
|
||||
|
||||
it "disables email authentication and invite-only mode" do
|
||||
post "/admin/config", params: { site_config: { allow_both_email_signup_and_login: false },
|
||||
confirmation: confirmation_message }
|
||||
expect(SiteConfig.allow_email_password_registration).to be(false)
|
||||
expect(SiteConfig.allow_email_password_login).to be(false)
|
||||
expect(SiteConfig.invite_only_mode).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Community Content" do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue