Allow Forem admins to enable an invite only mode. (#10758)

* Add invite only mode field to SiteConfig

* Add UI elements for invite only mode
This commit is contained in:
Jacob Herrington 2020-10-12 10:27:22 -05:00 committed by GitHub
parent ef613b0241
commit c37b283865
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 102 additions and 6 deletions

View file

@ -55,6 +55,7 @@ module Admin
github_secret
facebook_key
facebook_secret
invite_only_mode
allow_email_password_registration
primary_brand_color_hex
spam_trigger_terms

View file

@ -106,7 +106,11 @@ module ApplicationHelper
end
end
def any_selfserve_auth?
def invite_only_mode?
SiteConfig.invite_only_mode?
end
def any_enabled_auth_providers?
authentication_enabled_providers.any?
end

View file

@ -0,0 +1,19 @@
import { Controller } from 'stimulus';
export default class ConfigController extends Controller {
static targets = ['inviteOnlyMode', 'authenticationProviders'];
disableAuthenticationOptions() {
if (this.inviteOnlyModeTarget.checked) {
this.authenticationProvidersTarget.disabled = true;
document.querySelector(
'button[data-id=site_config_authentication_providers]',
).disabled = true;
} else {
this.authenticationProvidersTarget.disabled = false;
document.querySelector(
'button[data-id=site_config_authentication_providers]',
).disabled = false;
}
}
}

View file

@ -122,6 +122,10 @@ module Constants
description: "Used to authenticate with your health check endpoints.",
placeholder: "a secure token"
},
invite_only_mode: {
description: "Only users invited by email can join this community.",
placeholder: ""
},
jobs_url: {
description: "URL of the website where open positions are posted",
placeholder: "Jobs URL"

View file

@ -23,6 +23,7 @@ class SiteConfig < RailsSettings::Base
# Authentication
field :allow_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
field :twitter_key, type: :string, default: ApplicationConfig["TWITTER_KEY"]
field :twitter_secret, type: :string, default: ApplicationConfig["TWITTER_SECRET"]
field :github_key, type: :string, default: ApplicationConfig["GITHUB_KEY"]

View file

@ -44,6 +44,8 @@ module Authentication
# TODO: [@forem/oss] ideally this should be "available - disabled"
# we can get there once we have feature flags
def self.enabled
return [] if SiteConfig.invite_only_mode
SiteConfig.authentication_providers.map(&:to_sym).sort
end

View file

@ -1,4 +1,4 @@
<div class="grid gap-6">
<div class="grid gap-6" data-controller="config">
<div class="crayons-notice crayons-notice--info" role="alert">
<p class="mb-1">
Only admins with explicit <strong>single resource admin</strong> role may make changes to site config. Even super admins require this permission.
@ -116,6 +116,11 @@
expanded: "false"
} %>
<div id="authenticationBodyContainer" class="card-body collapse hide" aria-labelledby="authenticationBodyContainer">
<div class="form-group">
<%= admin_config_label :invite_only_mode %>
<%= f.check_box :invite_only_mode, checked: SiteConfig.invite_only_mode, data: { action: "config#disableAuthenticationOptions", target: "config.inviteOnlyMode" } %>
<div class="alert alert-info"><%= Constants::SiteConfig::DETAILS[:invite_only_mode][:description] %></div>
</div>
<div class="form-group">
<%= admin_config_label :allow_email_password_registration %>
<%= f.check_box :allow_email_password_registration, checked: SiteConfig.allow_email_password_registration %>
@ -131,7 +136,8 @@
authentication_enabled_providers.map(&:provider_name),
),
multiple: true,
class: "form-control selectpicker" %>
class: "form-control selectpicker",
data: { target: "config.authenticationProviders" } %>
<div class="alert alert-info"><%= Constants::SiteConfig::DETAILS[:authentication_providers][:description] %></div>
</div>
<div class="crayons-notice crayons-notice--info mb-4">

View file

@ -1,7 +1,7 @@
<div id="sidebar-wrapper-right" class="sidebar-wrapper sidebar-wrapper-right crayons-layout__sidebar-right">
<div class="sidebar-bg" id="sidebar-bg-right"></div>
<aside class="side-bar sidebar-additional showing grid gap-4" id="sidebar-additional">
<% unless user_signed_in? || !any_selfserve_auth? %>
<% unless user_signed_in? || !any_enabled_auth_providers? %>
<section class="crayons-card crayons-card--secondary signin-cta-widget">
<div class="authentication-widget__container">
<figure class="authentication-widget__image-container">

View file

@ -2,7 +2,11 @@
<div class="registration crayons-card">
<div class="registration__content">
<h1 class="registration__title">
Welcome to <%= community_name %>
<% if params[:state] == "new-user" && invite_only_mode? %>
<%= community_name %> is invite only.
<% else %>
Welcome to <%= community_name %>
<% end %>
</h1>
<p class="registration__description">
<a href="/"><%= community_name %></a> is a community of

View file

@ -15,7 +15,7 @@
</strong>
<br>
<% end %>
<% if any_selfserve_auth? %>
<% if any_enabled_auth_providers? %>
If you haven't created an account, we recommend signing up with social authentication below.
<% end %>
Contact <%= email_link %> if you continue having trouble.

View file

@ -78,6 +78,25 @@ RSpec.describe "/admin/config", type: :request do
confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq([provider])
end
context "when authentication providers are present" do
before do
SiteConfig.authentication_providers = Authentication::Providers.available.map(&:to_s)
end
it "allows authentication providers to be unset" do
new_provider = Array.wrap(SiteConfig.authentication_providers.pop.to_s)
post "/admin/config", params: { site_config: { authentication_providers: new_provider },
confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq(new_provider)
end
it "allows all authentication providers to be unset" do
post "/admin/config", params: { site_config: { authentication_providers: [] },
confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to be_empty
end
end
end
describe "Community Content" do

View file

@ -220,4 +220,16 @@ RSpec.describe "Authenticating with Facebook" do
end
end
end
context "when community is in invite only mode" do
before do
SiteConfig.invite_only_mode = true
end
it "doesn't present the authentication option" do
visit sign_up_path(state: "new-user")
expect(page).not_to have_text(sign_in_link)
expect(page).to have_text("invite only")
end
end
end

View file

@ -186,4 +186,16 @@ RSpec.describe "Authenticating with GitHub" do
end
end
end
context "when community is in invite only mode" do
before do
SiteConfig.invite_only_mode = true
end
it "doesn't present the authentication option" do
visit sign_up_path(state: "new-user")
expect(page).not_to have_text(sign_in_link)
expect(page).to have_text("invite only")
end
end
end

View file

@ -178,4 +178,16 @@ RSpec.describe "Authenticating with Twitter" do
end
end
end
context "when community is in invite only mode" do
before do
SiteConfig.invite_only_mode = true
end
it "doesn't present the authentication option" do
visit sign_up_path(state: "new-user")
expect(page).not_to have_text(sign_in_link)
expect(page).to have_text("invite only")
end
end
end