Allow communities to dictate authentication providers (#6639) [deploy]

* Allow communities to dictate authentication providers

* Include proper file

* Reset siteconfig value

Co-authored-by: rhymes <rhymesete@gmail.com>
This commit is contained in:
Ben Halpern 2020-03-18 16:41:39 -04:00 committed by GitHub
parent 4a4d83a6cf
commit 379aa4d1ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 148 additions and 92 deletions

View file

@ -25,7 +25,7 @@ class Internal::ConfigsController < Internal::ApplicationController
campaign_sidebar_image
main_social_image favicon_url logo_svg
rate_limit_follow_count_daily
ga_view_id ga_fetch_rate community_description
ga_view_id ga_fetch_rate community_description authentication_providers
mailchimp_newsletter_id mailchimp_sustaining_members_id
mailchimp_tag_moderators_id mailchimp_community_moderators_id
periodic_email_digest_max periodic_email_digest_min suggested_tags
@ -43,6 +43,7 @@ class Internal::ConfigsController < Internal::ApplicationController
def clean_up_params
config = params[:site_config]
config[:suggested_tags] = config[:suggested_tags].downcase.delete(" ") if config[:suggested_tags]
config[:authentication_providers] = config[:authentication_providers].downcase.delete(" ") if config[:authentication_providers]
config[:sidebar_tags] = config[:sidebar_tags].downcase.delete(" ") if config[:sidebar_tags]
end

View file

@ -19,6 +19,9 @@ class SiteConfig < RailsSettings::Base
# mascot account
field :mascot_user_id, type: :integer, default: 1
# Authentication
field :authentication_providers, type: :array, default: %w[twitter github]
# campaign
field :campaign_hero_html_variant_name, type: :string, default: ""
field :campaign_featured_tags, type: :array, default: %w[]
@ -60,4 +63,9 @@ class SiteConfig < RailsSettings::Base
# Tags
field :suggested_tags, type: :array, default: %w[beginners career computerscience javascript security ruby rails swift kotlin]
field :sidebar_tags, type: :array, default: %w[help challenge discuss explainlikeimfive meta watercooler]
# Helpful methods
def self.auth_allowed?(provider)
authentication_providers.include?(provider)
end
end

View file

@ -7,8 +7,12 @@
Join <%= ApplicationConfig["COMMUNITY_NAME"] %>
</header>
<div class="widget-body">
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="cta cta-button login-cta-button" data-no-instant>Sign In With Twitter</a>
<a href="/users/auth/github?state=navbar_basic" class="cta cta-button login-cta-button" data-no-instant>Sign In With GitHub</a>
<% if SiteConfig.auth_allowed?("twitter") %>
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="cta cta-button login-cta-button" data-no-instant>Sign In With Twitter</a>
<% end %>
<% if SiteConfig.auth_allowed?("github") %>
<a href="/users/auth/github?state=navbar_basic" class="cta cta-button login-cta-button" data-no-instant>Sign In With GitHub</a>
<% end %>
</div>
</div>
<% end %>

View file

@ -74,12 +74,16 @@
<h1>Great to have you</h1>
<% end %>
<div class="links">
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="sign-up-link" data-no-instant>
<%= inline_svg_tag("twitter-logo.svg", class: "icon-img", aria: true, title: "twitter logo") %> Sign In with Twitter
</a>
<a href="/users/auth/github?state=join-club-page_basic" class="sign-up-link" data-no-instant>
<%= inline_svg_tag("github-logo.svg", class: "icon-img", aria: true, title: "github logo") %> Sign In with GitHub
</a>
<% if SiteConfig.auth_allowed?("twitter") %>
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="sign-up-link" data-no-instant>
<%= inline_svg_tag("twitter-logo.svg", class: "icon-img", aria: true, title: "twitter logo") %> Sign In with Twitter
</a>
<% end %>
<% if SiteConfig.auth_allowed?("github") %>
<a href="/users/auth/github?state=join-club-page_basic" class="sign-up-link" data-no-instant>
<%= inline_svg_tag("github-logo.svg", class: "icon-img", aria: true, title: "github logo") %> Sign In with GitHub
</a>
<% end %>
<p><em>We require social login to prevent abuse.</em></p>
</div>
<p>Open Source 😇</p>

View file

@ -75,6 +75,20 @@
</div>
</div>
<div class="card mt-3">
<div class="card-header">Authentication</div>
<div class="card-body">
<div class="form-group">
<%= f.label :authentication_providers, "Authentication providers" %>
<%= f.text_field :authentication_providers,
class: "form-control",
value: SiteConfig.authentication_providers.join(","),
placeholder: "List of valid providers: comma separated, letters only e.g. twitter,github" %>
<div class="alert alert-info">How can users sign in? (More options coming)</div>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">Campaign</div>
<div class="card-body">
@ -346,34 +360,36 @@
</div>
</div>
<div class="row my-3" id="siteConfig">
<div class="card w-100">
<div class="card-header" id="appConfigHeader">
<h2 class="d-inline">Environment variables / AppConfig (readonly)</h2>
<button class="btn btn-secondary float-right" type="button" data-toggle="collapse"
data-target="#appConfigBodyContainer" aria-expanded="true" aria-controls="appConfigBodyContainer">
Toggle
</button>
</div>
<div id="appConfigBodyContainer" class="collapse show hide" aria-labelledby="appConfigHeader">
<table class="table">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<% ENVied.config.variables.each do |v| %>
<% if v.group.in?(ENVied.required_groups) %>
<tr>
<td><%= v.name %></td>
<td style="max-width: 750px;"><%= ApplicationConfig[v.name] %></td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
<% if current_user.has_role?(:single_resource_admin, Config) %>
<div class="row my-3" id="siteConfig">
<div class="card w-100">
<div class="card-header" id="appConfigHeader">
<h2 class="d-inline">Environment variables / AppConfig (readonly)</h2>
<button class="btn btn-secondary float-right" type="button" data-toggle="collapse"
data-target="#appConfigBodyContainer" aria-expanded="true" aria-controls="appConfigBodyContainer">
Toggle
</button>
</div>
<div id="appConfigBodyContainer" class="collapse show hide" aria-labelledby="appConfigHeader">
<table class="table">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<% ENVied.config.variables.each do |v| %>
<% if v.group.in?(ENVied.required_groups) %>
<tr>
<td><%= v.name %></td>
<td style="max-width: 750px;"><%= ApplicationConfig[v.name] %></td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
<% end %>

View file

@ -41,19 +41,23 @@
Sign In/Up
</div>
</a>
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" data-no-instant>
<div class="option">
Via Twitter
</div>
</a>
<a href="/users/auth/github?state=navbar_basic" data-no-instant id="second-last-nav-link">
<div class="option">
Via GitHub
</div>
</a>
<% if SiteConfig.auth_allowed?("twitter") %>
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" data-no-instant>
<div class="option">
Via Twitter
</div>
</a>
<% end %>
<% if SiteConfig.auth_allowed?("github") %>
<a href="/users/auth/github?state=navbar_basic" data-no-instant id="second-last-nav-link">
<div class="option">
Via GitHub
</div>
</a>
<% end %>
<a href="/p/information" id="last-nav-link">
<div class="option">
All about dev.to
All about <%= ApplicationConfig["COMMUNITY_NAME"] %>
</div>
</a>
<% end %>

View file

@ -17,12 +17,16 @@
<p>
We're a place where coders share, stay up-to-date and grow their careers.
</p>
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="sign-up-link cta" data-no-instant>
<img src="<%= asset_path("twitter-logo.svg") %>" class="icon-img" alt="Twitter logo" /> Auth With Twitter
</a>
<a href="/users/auth/github?state=signup-modal" class="sign-up-link cta" data-no-instant>
<img src="<%= asset_path("github-logo.svg") %>" class="icon-img" alt="GitHub logo" /> Auth With GitHub
</a>
<% if SiteConfig.auth_allowed?("twitter") %>
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="sign-up-link cta" data-no-instant>
<img src="<%= asset_path("twitter-logo.svg") %>" class="icon-img" alt="Twitter logo" /> Auth With Twitter
</a>
<% end %>
<% if SiteConfig.auth_allowed?("github") %>
<a href="/users/auth/github?state=signup-modal" class="sign-up-link cta" data-no-instant>
<img src="<%= asset_path("github-logo.svg") %>" class="icon-img" alt="GitHub logo" /> Auth With GitHub
</a>
<% end %>
<p>
<em>We strive for transparency and don't collect excess data.</em>
</p>

View file

@ -11,11 +11,8 @@
</h3>
<div class="button-container">
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="cta cta-button" aria-label="Sign in with Twitter." data-no-instant>
Sign In with Twitter
</a>
<a href="/users/auth/github?state=in-feed-cta" class="cta cta-button" aria-label="Sign in with GitHub." data-no-instant>
Sign In with GitHub
<a href="/enter" class="cta cta-button" aria-label="Sign up.">
Join Now
</a>
<div class="feed-cta-sub">
<em>We require social login to prevent abuse.</em>

View file

@ -1,20 +1,4 @@
<% unless @user.identities.exists?(provider: "github") %>
<div class="field">
<a href="/users/auth/github" class="big-button cta" data-no-instant>
<img src="<%= asset_path("github-logo.svg") %>" alt="github logo"> CONNECT GITHUB ACCOUNT
</a>
</div>
<hr />
<% end %>
<% unless @user.identities.exists?(provider: "twitter") %>
<div class="field">
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="big-button cta" data-no-instant>
<img src="<%= asset_path("twitter-logo.svg") %> " alt="twitter logo"> CONNECT TWITTER ACCOUNT
</a>
</div>
<hr />
<% end %>
<%= render "users/additional_authentication" %>
<h2>DEV API Keys</h2>
<p>You can generate personal API keys to use for authentication with the DEV API. The API is still in early beta though. The <a href="https://docs.dev.to/api/">DEV API documentation</a> contains further information.</a></p>

View file

@ -0,0 +1,19 @@
<% if SiteConfig.auth_allowed?("github") && !@user.identities.exists?(provider: "github") %>
<%= render "users/additional_authentication" %>
<div class="field">
<a href="/users/auth/github" class="big-button cta" data-no-instant>
<img src="<%= asset_path("github-logo.svg") %>" alt="github logo"> CONNECT GITHUB ACCOUNT
</a>
</div>
<hr />
<% end %>
<% if SiteConfig.auth_allowed?("twitter") && !@user.identities.exists?(provider: "twitter") %>
<div class="field">
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="big-button cta" data-no-instant>
<img src="<%= asset_path("twitter-logo.svg") %> " alt="twitter logo"> CONNECT TWITTER ACCOUNT
</a>
</div>
<hr />
<% end %>

View file

@ -1,20 +1,7 @@
<%= javascript_packs_with_chunks_tag "colorPreview", defer: true %>
<% unless @user.identities.exists?(provider: 'github') %>
<div class="field">
<a href="/users/auth/github" class="big-button cta" data-no-instant>
<img src="<%= asset_path("github-logo.svg") %>" alt="github logo" /> CONNECT GITHUB ACCOUNT
</a>
</div>
<% end %>
<%= render "users/additional_authentication" %>
<% unless @user.identities.exists?(provider: 'twitter') %>
<div class="field">
<a href="/users/auth/twitter?callback_url=<%= ApplicationConfig["APP_PROTOCOL"] %><%= ApplicationConfig["APP_DOMAIN"] %>/users/auth/twitter/callback" class="big-button cta" data-no-instant>
<img src="<%= asset_path("twitter-logo.svg") %>" alt="twitter logo" /> CONNECT TWITTER ACCOUNT
</a>
</div>
<% end %>
<h4>
<a href="https://<%= ApplicationConfig["APP_DOMAIN"] %>/<%= current_user.username %>" aria-label="Go to your profile page">
<img src="https://d2fltix0v2e0sb.cloudfront.net/dev-badge.svg"

View file

@ -206,6 +206,18 @@ RSpec.describe "/internal/config", type: :request do
expect(SiteConfig.sidebar_tags).to eq(%w[hey haha hoho bobofofo])
end
end
describe "Authentication" do
it "removes space authentication_providers" do
post "/internal/config", params: { site_config: { authentication_providers: "github, twitter" }, confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq(%w[github twitter])
end
it "downcases authentication_providers" do
post "/internal/config", params: { site_config: { authentication_providers: "GitHub, Twitter" }, confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq(%w[github twitter])
end
end
end
end
# rubocop:enable RSpec/NestedGroups

View file

@ -55,6 +55,22 @@ RSpec.describe "UserSettings", type: :request do
get "/settings/account"
expect(response.body).to include ghost_account_message
end
it "renders CONNECT_WITH_TWITTER and user with only github identity" do
user.identities.where(provider: "twitter").delete_all
get "/settings"
expect(response.body).to include "CONNECT TWITTER ACCOUNT"
end
it "renders does not render CONNECT_WITH_TWITTER if SiteConfig does not include Twitter auth" do
user.identities.where(provider: "twitter").destroy_all
current_auth_value = SiteConfig.authentication_providers
SiteConfig.authentication_providers = ["github"]
SiteConfig.clear_cache
get "/settings"
expect(response.body).not_to include "CONNECT TWITTER ACCOUNT"
SiteConfig.authentication_providers = current_auth_value # restore prior value
end
end
end

View file

@ -61,7 +61,7 @@ RSpec.describe "Authenticating with twitter" do
expect(page).to have_link "Sign In/Up"
expect(page).to have_link "Via Twitter"
expect(page).to have_link "Via GitHub"
expect(page).to have_link "All about dev.to"
expect(page).to have_link "All about #{ApplicationConfig['COMMUNITY_NAME']}"
end
end
end