diff --git a/Gemfile b/Gemfile index f246c1e76..acc098082 100644 --- a/Gemfile +++ b/Gemfile @@ -75,7 +75,8 @@ gem "rack-attack", "~> 6.5.0" # Used to throttle requests to prevent brute force gem "rack-cors", "~> 1.1" # Middleware that will make Rack-based apps CORS compatible gem "rack-timeout", "~> 0.6" # Rack middleware which aborts requests that have been running for longer than a specified timeout gem "rails", "~> 6.1" # Ruby on Rails -gem "rails-settings-cached", ">= 2.1.1" # Settings plugin for Rails that makes managing a table of global key, value pairs easy. +# Pinned since we have a monkey-patch against this version +gem "rails-settings-cached", "= 2.5.2" # Settings plugin for Rails that makes managing a table of global key, value pairs easy. gem "ransack", "~> 2.4" # Searching and sorting gem "recaptcha", "~> 5.7", require: "recaptcha/rails" # Helpers for the reCAPTCHA API gem "redcarpet", "~> 3.5" # A fast, safe and extensible Markdown to (X)HTML parser diff --git a/Gemfile.lock b/Gemfile.lock index 1c90fcdef..290ea0870 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,7 +86,7 @@ GEM activerecord (>= 5.0, < 6.2) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) - ahoy_email (2.0.2) + ahoy_email (2.0.3) actionmailer (>= 5) addressable (>= 2.3.2) nokogiri @@ -168,7 +168,7 @@ GEM activesupport (>= 3.2.0) carrierwave fastimage - chartkick (3.4.2) + chartkick (4.0.2) childprocess (3.0.0) cloudinary (1.20.0) aws_cf_signer @@ -424,13 +424,13 @@ GEM listen (3.5.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.9.0) + loofah (2.9.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.2.8) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.0) + marcel (1.0.1) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) memory_profiler (1.0.0) @@ -462,16 +462,12 @@ GEM http-2 (~> 0.11) netrc (0.11.0) nio4r (2.5.7) - nokogiri (1.11.3-arm64-darwin) - racc (~> 1.4) - nokogiri (1.11.3-x86_64-darwin) - racc (~> 1.4) nokogiri (1.11.3-x86_64-linux) racc (~> 1.4) notiffany (0.1.3) nenv (~> 0.1) shellany (~> 0.0) - oauth (0.5.5) + oauth (0.5.6) oauth2 (1.4.7) faraday (>= 0.8, < 2.0) jwt (>= 1.0, < 3.0) @@ -508,7 +504,7 @@ GEM rack orm_adapter (0.5.0) parallel (1.20.1) - parser (3.0.0.0) + parser (3.0.1.0) ast (~> 2.4.1) patron (0.13.3) pg (1.2.3) @@ -843,8 +839,6 @@ GEM zonebie (0.6.1) PLATFORMS - arm64-darwin - x86_64-darwin x86_64-linux DEPENDENCIES @@ -940,7 +934,7 @@ DEPENDENCIES rack-host-redirect (~> 1.3) rack-timeout (~> 0.6) rails (~> 6.1) - rails-settings-cached (>= 2.1.1) + rails-settings-cached (= 2.5.2) ransack (~> 2.4) recaptcha (~> 5.7) redcarpet (~> 3.5) diff --git a/app/assets/javascripts/initializers/runtime.js b/app/assets/javascripts/initializers/runtime.js index 3defd6f6d..b23fae7dd 100644 --- a/app/assets/javascripts/initializers/runtime.js +++ b/app/assets/javascripts/initializers/runtime.js @@ -56,7 +56,7 @@ class Runtime { } else if (/Android/i.test(window.navigator.userAgent)) { return 'Android'; } else if (/Linux/i.test(window.navigator.platform)) { - return 'Linux'; + return 'Linux'; } return 'Unsupported'; diff --git a/app/controllers/admin/configs_controller.rb b/app/controllers/admin/configs_controller.rb index 742a0b291..2c21106b3 100644 --- a/app/controllers/admin/configs_controller.rb +++ b/app/controllers/admin/configs_controller.rb @@ -1,31 +1,9 @@ module Admin - class ConfigsController < Admin::ApplicationController - include SiteConfigParams - - EMOJI_ONLY_FIELDS = %w[community_emoji].freeze - IMAGE_FIELDS = - %w[ - main_social_image - logo_png - secondary_logo_url - campaign_sidebar_image - mascot_image_url - mascot_footer_image_url - onboarding_background_image - ].freeze - - VALID_URL = %r{\A(http|https)://([/|.\w\s-])*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?\z}.freeze - - layout "admin" - - before_action :extra_authorization_and_confirmation, only: [:create] - - def show - @confirmation_text = confirmation_text - end + class ConfigsController < Admin::SettingsController + include SettingsParams def create - result = SiteConfigs::Upsert.call(site_config_params) + result = ::Settings::Upsert.call(settings_params) if result.success? Audit::Logger.log(:internal, current_user, params.dup) bust_content_change_caches @@ -34,20 +12,5 @@ module Admin redirect_to admin_config_path, alert: "😭 #{result.errors.to_sentence}" end end - - private - - def confirmation_text - "My username is @#{current_user.username} and this action is 100% safe and appropriate." - end - - def raise_confirmation_mismatch_error - raise ActionController::BadRequest.new, "The confirmation key does not match" - end - - def extra_authorization_and_confirmation - not_authorized unless current_user.has_role?(:super_admin) - raise_confirmation_mismatch_error if params.require(:confirmation) != confirmation_text - end end end diff --git a/app/controllers/admin/settings/authentications_controller.rb b/app/controllers/admin/settings/authentications_controller.rb new file mode 100644 index 000000000..f99f16f56 --- /dev/null +++ b/app/controllers/admin/settings/authentications_controller.rb @@ -0,0 +1,22 @@ +module Admin + module Settings + class AuthenticationsController < Admin::ApplicationController + def create + result = ::Authentication::SettingsUpsert.call(settings_params) + + if result.success? + Audit::Logger.log(:internal, current_user, params.dup) + redirect_to admin_config_path, notice: "Site configuration was successfully updated." + else + redirect_to admin_config_path, alert: "😭 #{result.errors.to_sentence}" + end + end + + def settings_params + params + .require(:settings_authentication) + .permit(*::Settings::Authentication.keys, :auth_providers_to_enable) + end + end + end +end diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb new file mode 100644 index 000000000..6cd297df6 --- /dev/null +++ b/app/controllers/admin/settings_controller.rb @@ -0,0 +1,30 @@ +module Admin + class SettingsController < Admin::ApplicationController + MISMATCH_ERROR = "The confirmation key does not match".freeze + + before_action :extra_authorization_and_confirmation, only: [:create] + + layout "admin" + + def create; end + + def show + @confirmation_text = confirmation_text + end + + private + + def extra_authorization_and_confirmation + not_authorized unless current_user.has_role?(:super_admin) + raise_confirmation_mismatch_error if params.require(:confirmation) != confirmation_text + end + + def confirmation_text + "My username is @#{current_user.username} and this action is 100% safe and appropriate." + end + + def raise_confirmation_mismatch_error + raise ActionController::BadRequest.new, MISMATCH_ERROR + end + end +end diff --git a/app/controllers/api/v0/admin/configs_controller.rb b/app/controllers/api/v0/admin/configs_controller.rb index f85376f82..9ab9ffdf8 100644 --- a/app/controllers/api/v0/admin/configs_controller.rb +++ b/app/controllers/api/v0/admin/configs_controller.rb @@ -2,7 +2,7 @@ module Api module V0 module Admin class ConfigsController < ApiController - include SiteConfigParams + include SettingsParams before_action :authenticate_with_api_key_or_current_user! before_action :authorize_super_admin @@ -13,16 +13,30 @@ module Api end def update - result = SiteConfigs::Upsert.call(site_config_params) - if result.success? - @site_configs = SiteConfig.all + # NOTE: citizen428 - this is not going to scale but I want to wait + # until we extract at least one more settings model before deciding + # how to change this. + settings_result = ::Settings::Upsert.call(settings_params) + auth_settings_result = ::Authentication::SettingsUpsert.call(auth_settings_params) + + if settings_result.success? && auth_settings_result.success? + @site_configs = SiteConfig.all + Settings::Authentication.all Audit::Logger.log(:internal, @user, params.dup) bust_content_change_caches render "show" else - render json: { error: result.errors.to_sentence, status: 422 }, status: :unprocessable_entity + errors = settings_result.errors + auth_settings_result.errors + render json: { error: errors.to_sentence, status: 422 }, status: :unprocessable_entity end end + + private + + def auth_settings_params + params + .require(:site_config) + .permit(*::Settings::Authentication.keys, :providers_to_enable) + end end end end diff --git a/app/controllers/concerns/site_config_params.rb b/app/controllers/concerns/settings_params.rb similarity index 61% rename from app/controllers/concerns/site_config_params.rb rename to app/controllers/concerns/settings_params.rb index 2ab5e060d..bb4e8cd83 100644 --- a/app/controllers/concerns/site_config_params.rb +++ b/app/controllers/concerns/settings_params.rb @@ -1,16 +1,26 @@ -module SiteConfigParams - SPECIAL_PARAMS_TO_ADD = - %w[authentication_providers email_addresses meta_keywords credit_prices_in_cents auth_providers_to_enable].freeze - def site_config_params +module SettingsParams + SPECIAL_PARAMS_TO_ADD = %w[ + credit_prices_in_cents + email_addresses + meta_keywords + ].freeze + + def settings_params has_emails = params.dig(:site_config, :email_addresses).present? params[:site_config][:email_addresses][:default] = ApplicationConfig["DEFAULT_EMAIL"] if has_emails + params.require(:site_config)&.permit( - (SiteConfig.keys + SPECIAL_PARAMS_TO_ADD).map(&:to_sym), - authentication_providers: [], + settings_keys.map(&:to_sym), social_media_handles: SiteConfig.social_media_handles.keys, email_addresses: SiteConfig.email_addresses.keys, meta_keywords: SiteConfig.meta_keywords.keys, credit_prices_in_cents: SiteConfig.credit_prices_in_cents.keys, ) end + + private + + def settings_keys + SiteConfig.keys + SPECIAL_PARAMS_TO_ADD + end end diff --git a/app/controllers/feedback_messages_controller.rb b/app/controllers/feedback_messages_controller.rb index 8d512a32f..e9bcf01e2 100644 --- a/app/controllers/feedback_messages_controller.rb +++ b/app/controllers/feedback_messages_controller.rb @@ -51,7 +51,7 @@ class FeedbackMessagesController < ApplicationController private def recaptcha_verified? - recaptcha_params = { secret_key: SiteConfig.recaptcha_secret_key } + recaptcha_params = { secret_key: Settings::Authentication.recaptcha_secret_key } params["g-recaptcha-response"] && verify_recaptcha(recaptcha_params) end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 7852342e9..afa7db257 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -13,7 +13,8 @@ class RegistrationsController < Devise::RegistrationsController end def create - not_authorized unless SiteConfig.allow_email_password_registration || SiteConfig.waiting_on_first_user + not_authorized unless Settings::Authentication.allow_email_password_registration || + SiteConfig.waiting_on_first_user not_authorized if SiteConfig.waiting_on_first_user && ENV["FOREM_OWNER_SECRET"].present? && ENV["FOREM_OWNER_SECRET"] != params[:user][:forem_owner_secret] @@ -51,13 +52,13 @@ class RegistrationsController < Devise::RegistrationsController end def recaptcha_verified? - recaptcha_params = { secret_key: SiteConfig.recaptcha_secret_key } + recaptcha_params = { secret_key: Settings::Authentication.recaptcha_secret_key } params["g-recaptcha-response"] && verify_recaptcha(recaptcha_params) end def check_allowed_email(resource) domain = resource.email.split("@").last - allow_list = SiteConfig.allowed_registration_email_domains + allow_list = Settings::Authentication.allowed_registration_email_domains return if allow_list.empty? || allow_list.include?(domain) resource.email = nil diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e1f426cf5..3855c64a5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -96,7 +96,7 @@ module ApplicationHelper end def invite_only_mode? - SiteConfig.invite_only_mode? + Settings::Authentication.invite_only_mode? end def any_enabled_auth_providers? @@ -274,7 +274,7 @@ module ApplicationHelper estimated_user_count > LARGE_USERBASE_THRESHOLD end - def admin_config_label(method, content = nil) + def admin_config_label(method, content = nil, model: SiteConfig) content ||= tag.span(method.to_s.humanize) if method.to_sym.in?(VerifySetupCompleted::MANDATORY_CONFIGS) @@ -282,7 +282,8 @@ module ApplicationHelper content = safe_join([content, required]) end - tag.label(content, class: "site-config__label crayons-field__label", for: "site_config_#{method}") + label_prefix = model.name.split("::").map(&:underscore).join("_") + tag.label(content, class: "site-config__label crayons-field__label", for: "#{label_prefix}_#{method}") end def admin_config_description(content) diff --git a/app/helpers/authentication_helper.rb b/app/helpers/authentication_helper.rb index abd35d7e3..f04c72a5f 100644 --- a/app/helpers/authentication_helper.rb +++ b/app/helpers/authentication_helper.rb @@ -46,8 +46,9 @@ module AuthenticationHelper end def invite_only_mode_or_no_enabled_auth_options - SiteConfig.invite_only_mode || - (authentication_enabled_providers.none? && !SiteConfig.allow_email_password_registration) + Settings::Authentication.invite_only_mode || + (authentication_enabled_providers.none? && + !Settings::Authentication.allow_email_password_registration) end def tooltip_class_on_auth_provider_enablebtn diff --git a/app/javascript/admin/controllers/config_controller.js b/app/javascript/admin/controllers/config_controller.js index a04b05ebe..e4c7c1b0e 100644 --- a/app/javascript/admin/controllers/config_controller.js +++ b/app/javascript/admin/controllers/config_controller.js @@ -293,8 +293,12 @@ export default class ConfigController extends Controller { .forEach((provider) => { const { providerName } = provider.dataset; if ( - !document.getElementById(`site_config_${providerName}_key`).value || - !document.getElementById(`site_config_${providerName}_secret`).value + !document.getElementById( + `settings_authentication_${providerName}_key`, + ).value || + !document.getElementById( + `settings_authentication_${providerName}_secret`, + ).value ) { providersWithMissingKeys.push(providerName); } diff --git a/app/javascript/analytics/dashboard.js b/app/javascript/analytics/dashboard.js index b4365fd64..c078c8805 100644 --- a/app/javascript/analytics/dashboard.js +++ b/app/javascript/analytics/dashboard.js @@ -1,7 +1,9 @@ import { callHistoricalAPI, callReferrersAPI } from './client'; function resetActive(activeButton) { - const buttons = document.querySelectorAll('.crayons-tabs--analytics .crayons-tabs__item'); + const buttons = document.querySelectorAll( + '.crayons-tabs--analytics .crayons-tabs__item', + ); for (let i = 0; i < buttons.length; i += 1) { const button = buttons[i]; button.classList.remove('crayons-tabs__item--current'); diff --git a/app/javascript/shared/components/useKeyboardShortcuts.js b/app/javascript/shared/components/useKeyboardShortcuts.js index 28e40a626..2037ffc45 100644 --- a/app/javascript/shared/components/useKeyboardShortcuts.js +++ b/app/javascript/shared/components/useKeyboardShortcuts.js @@ -27,7 +27,7 @@ function isFormField(element) { /** * Function to handle converting key presses to callback functions - * + * * @param {KeyboardEvent} e Keyboard event * @param {String} keys special keys formatted in a string * @param {Array} chain array of past keys @@ -96,7 +96,7 @@ export function useKeyboardShortcuts( const [keyChain, setKeyChain] = useState([]); const [mergedOptions, setMergedOptions] = useState({ ...defaultOptions, - ...options + ...options, }); // update mergedOptions if options prop changes diff --git a/app/lib/constants/settings/authentication.rb b/app/lib/constants/settings/authentication.rb new file mode 100644 index 000000000..017cf5f6f --- /dev/null +++ b/app/lib/constants/settings/authentication.rb @@ -0,0 +1,82 @@ +module Constants + module Settings + module Authentication + DETAILS = { + allowed_registration_email_domains: { + description: "Restrict registration to only certain emails? (comma-separated list)", + placeholder: "dev.to, forem.com, codenewbie.org" + }, + apple_client_id: { + description: + "The \"App Bundle\" code for the Authentication Service configured in the Apple Developer Portal", + placeholder: "com.example.app" + }, + apple_team_id: { + description: + "The \"Team ID\" of your Apple Developer Account", + placeholder: "" + }, + apple_key_id: { + description: + "The \"Key ID\" from the Authentication Service configured in the Apple Developer Portal", + placeholder: "" + }, + apple_pem: { + description: + "The \"PEM\" key from the Authentication Service configured in the Apple Developer Portal", + placeholder: "-----BEGIN PRIVATE KEY-----\nMIGTAQrux...QPe8Yb\n-----END PRIVATE KEY-----\\n" + }, + display_email_domain_allow_list_publicly: { + description: "Do you want to display the list of allowed domains, or keep it private?" + }, + facebook_key: { + description: + "The \"App ID\" portion of the Basic Settings section of the App page on the Facebook Developer Portal", + placeholder: "" + }, + facebook_secret: { + description: + "The \"App Secret\" portion of the Basic Settings section of the App page on the Facebook Developer Portal", + placeholder: "" + }, + github_key: { + description: "The \"Client ID\" portion of the GitHub Oauth Apps portal", + placeholder: "" + }, + github_secret: { + description: "The \"Client Secret\" portion of the GitHub Oauth Apps portal", + placeholder: "" + }, + invite_only_mode: { + description: "Only users invited by email can join this community.", + placeholder: "" + }, + recaptcha_site_key: { + description: "Add the site key for Google reCAPTCHA, which is used for reporting abuse", + placeholder: "What is the Google reCAPTCHA site key?" + }, + recaptcha_secret_key: { + description: "Add the secret key for Google reCAPTCHA, which is used for reporting abuse", + placeholder: "What is the Google reCAPTCHA secret key?" + }, + 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", + placeholder: "" + }, + twitter_key: { + description: "The \"API key\" portion of consumer keys in the Twitter developer portal.", + placeholder: "" + }, + twitter_secret: { + description: "The \"API secret key\" portion of consumer keys in the Twitter developer portal.", + placeholder: "" + }, + providers: { + description: "How can users sign in?", + placeholder: "" + } + }.freeze + end + end +end diff --git a/app/lib/constants/site_config.rb b/app/lib/constants/site_config.rb index 14d73bdc7..be0a4fd80 100644 --- a/app/lib/constants/site_config.rb +++ b/app/lib/constants/site_config.rb @@ -4,19 +4,6 @@ module Constants SVG_PLACEHOLDER = "".freeze DETAILS = { - 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", - placeholder: "" - }, - allowed_registration_email_domains: { - description: "Restrict registration to only certain emails? (comma-separated list)", - placeholder: "dev.to, forem.com, codenewbie.org" - }, - authentication_providers: { - description: "How can users sign in?", - placeholder: "" - }, campaign_articles_require_approval: { description: "", placeholder: "Campaign stories show up on sidebar with approval?" @@ -90,9 +77,6 @@ module Constants default_font: { description: "Determines the default Base Reading Font (registered users can change this in their UX settings)" }, - display_email_domain_allow_list_publicly: { - description: "Do you want to display the list of allowed domains, or keep it private?" - }, display_jobs_banner: { description: "Display a jobs banner that points users to the jobs page when they type 'job'" \ "or 'jobs' in the search box", @@ -110,36 +94,6 @@ module Constants description: "The label for the top of the experience level range of a post", placeholder: "Senior Devs" }, - facebook_key: { - description: - "The \"App ID\" portion of the Basic Settings section of the App page on the Facebook Developer Portal", - placeholder: "" - }, - facebook_secret: { - description: - "The \"App Secret\" portion of the Basic Settings section of the App page on the Facebook Developer Portal", - placeholder: "" - }, - apple_client_id: { - description: - "The \"App Bundle\" code for the Authentication Service configured in the Apple Developer Portal", - placeholder: "com.example.app" - }, - apple_team_id: { - description: - "The \"Team ID\" of your Apple Developer Account", - placeholder: "" - }, - apple_key_id: { - description: - "The \"Key ID\" from the Authentication Service configured in the Apple Developer Portal", - placeholder: "" - }, - apple_pem: { - description: - "The \"PEM\" key from the Authentication Service configured in the Apple Developer Portal", - placeholder: "-----BEGIN PRIVATE KEY-----\nMIGTAQrux...QPe8Yb\n-----END PRIVATE KEY-----\\n" - }, favicon_url: { description: "Used as the site favicon", placeholder: IMAGE_PLACEHOLDER @@ -157,14 +111,6 @@ module Constants description: "Determines background/border of buttons etc. Must be dark enough to contrast with white text.", placeholder: "#0a0a0a" }, - github_key: { - description: "The \"Client ID\" portion of the GitHub Oauth Apps portal", - placeholder: "" - }, - github_secret: { - description: "The \"Client Secret\" portion of the GitHub Oauth Apps portal", - placeholder: "" - }, ga_tracking_id: { description: "Google Analytics Tracking ID, e.g. UA-71991000-1", placeholder: "" @@ -177,10 +123,6 @@ module Constants description: "Minimum score needed for a post to show up on the unauthenticated home page.", placeholder: "0" }, - 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" @@ -258,14 +200,6 @@ module Constants description: "Determines how often periodic email digests are sent", placeholder: 2 }, - recaptcha_site_key: { - description: "Add the site key for Google reCAPTCHA, which is used for reporting abuse", - placeholder: "What is the Google reCAPTCHA site key?" - }, - recaptcha_secret_key: { - description: "Add the secret key for Google reCAPTCHA, which is used for reporting abuse", - placeholder: "What is the Google reCAPTCHA secret key?" - }, secondary_logo_url: { description: "A place for an alternate logo, if you have one. Used throughout member onboarding and in some sign in forms.", placeholder: IMAGE_PLACEHOLDER @@ -327,14 +261,6 @@ module Constants description: "Used as the twitter hashtag of the community", placeholder: "#DEVCommunity" }, - twitter_key: { - description: "The \"API key\" portion of consumer keys in the Twitter developer portal.", - placeholder: "" - }, - twitter_secret: { - description: "The \"API secret key\" portion of consumer keys in the Twitter developer portal.", - placeholder: "" - }, user_considered_new_days: { description: "The number of days a user is considered new. The default is 3 days, but you can disable this entirely by inputting 0.", placeholder: ::SiteConfig.user_considered_new_days diff --git a/app/models/settings/authentication.rb b/app/models/settings/authentication.rb new file mode 100644 index 000000000..56db61652 --- /dev/null +++ b/app/models/settings/authentication.rb @@ -0,0 +1,44 @@ +module Settings + class Authentication < RailsSettings::Base + self.table_name = :settings_authentications + + # The configuration is cached, change this if you want to force update + # the cache, or call Settings::Authentication.clear_cache + cache_prefix { "v1" } + + field :allow_email_password_login, type: :boolean, default: true + field :allow_email_password_registration, type: :boolean, default: false + field :allowed_registration_email_domains, type: :array, default: %w[], validates: { + valid_domain_csv: true + } + field :apple_client_id, type: :string + field :apple_key_id, type: :string + field :apple_pem, type: :string + field :apple_team_id, type: :string + field :display_email_domain_allow_list_publicly, type: :boolean, default: false + field :facebook_key, type: :string + field :facebook_secret, type: :string + field :github_key, type: :string, default: ApplicationConfig["GITHUB_KEY"] + field :github_secret, type: :string, default: ApplicationConfig["GITHUB_SECRET"] + field :invite_only_mode, type: :boolean, default: false + field :providers, type: :array, default: %w[] + field :require_captcha_for_email_password_registration, type: :boolean, default: false + field :twitter_key, type: :string, default: ApplicationConfig["TWITTER_KEY"] + field :twitter_secret, type: :string, default: ApplicationConfig["TWITTER_SECRET"] + + # Google ReCATPCHA keys + field :recaptcha_site_key, type: :string, default: ApplicationConfig["RECAPTCHA_SITE"] + field :recaptcha_secret_key, type: :string, default: ApplicationConfig["RECAPTCHA_SECRET"] + + # Apple uses different keys than the usual `PROVIDER_NAME_key` or + # `PROVIDER_NAME_secret` so these will help the generalized authentication + # code to work, i.e. https://github.com/forem/forem/blob/master/app/helpers/authentication_helper.rb#L26-L29 + def self.apple_key + return unless apple_client_id.present? && apple_key_id.present? && + apple_pem.present? && apple_team_id.present? + + "present" + end + singleton_class.alias_method(:apple_secret, :apple_key) + end +end diff --git a/app/models/site_config.rb b/app/models/site_config.rb index b1bc480c0..57d9a873c 100644 --- a/app/models/site_config.rb +++ b/app/models/site_config.rb @@ -29,26 +29,12 @@ class SiteConfig < RailsSettings::Base field :health_check_token, type: :string field :video_encoder_key, type: :string - # Authentication - field :allow_email_password_registration, type: :boolean, default: false - field :allow_email_password_login, type: :boolean, default: true + # NOTE: @citizen428 These two values will be removed once we fully migrated + # to Settings::Authentication. Until then we need them for the data update script. field :allowed_registration_email_domains, type: :array, default: %w[], validates: { valid_domain_csv: true } - field :display_email_domain_allow_list_publicly, type: :boolean, default: false - field :require_captcha_for_email_password_registration, type: :boolean, default: false field :authentication_providers, type: :array, default: %w[] - 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"] - field :github_secret, type: :string, default: ApplicationConfig["GITHUB_SECRET"] - field :facebook_key, type: :string - field :facebook_secret, type: :string - field :apple_client_id, type: :string - field :apple_key_id, type: :string - field :apple_pem, type: :string - field :apple_team_id, type: :string # Campaign field :campaign_call_to_action, type: :string, default: "Share your project" @@ -98,10 +84,6 @@ class SiteConfig < RailsSettings::Base # Google Analytics Tracking ID, e.g. UA-71991000-1 field :ga_tracking_id, type: :string, default: ApplicationConfig["GA_TRACKING_ID"] - # Google ReCATPCHA keys - field :recaptcha_site_key, type: :string, default: ApplicationConfig["RECAPTCHA_SITE"] - field :recaptcha_secret_key, type: :string, default: ApplicationConfig["RECAPTCHA_SECRET"] - # Images field :main_social_image, type: :string, @@ -248,17 +230,6 @@ class SiteConfig < RailsSettings::Base app_domain == "dev.to" end - # Apple uses different keys than the usual `PROVIDER_NAME_key` or - # `PROVIDER_NAME_secret` so these will help the generalized authentication - # code to work, i.e. https://github.com/forem/forem/blob/master/app/helpers/authentication_helper.rb#L26-L29 - def self.apple_key - return unless apple_client_id.present? && apple_key_id.present? && - apple_pem.present? && apple_team_id.present? - - "present" - end - singleton_class.__send__(:alias_method, :apple_secret, :apple_key) - # To get default values def self.get_default(field) get_field(field)[:default] diff --git a/app/services/authentication/providers.rb b/app/services/authentication/providers.rb index 1275318d1..77550b89b 100644 --- a/app/services/authentication/providers.rb +++ b/app/services/authentication/providers.rb @@ -44,9 +44,9 @@ 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 + return [] if Settings::Authentication.invite_only_mode - SiteConfig.authentication_providers.map(&:to_sym).sort + Settings::Authentication.providers.map(&:to_sym).sort end def self.enabled_for_user(user) diff --git a/app/services/authentication/settings_upsert.rb b/app/services/authentication/settings_upsert.rb new file mode 100644 index 000000000..e712e40be --- /dev/null +++ b/app/services/authentication/settings_upsert.rb @@ -0,0 +1,68 @@ +module Authentication + class SettingsUpsert + attr_reader :errors + + def self.call(configs) + new(configs).call + end + + def initialize(configs) + @configs = configs + @errors = [] + end + + def call + upsert_configs + self + end + + def success? + @errors.none? + end + + private + + # NOTE: @citizen428 - This was adapted from Settings::Upsert. I'll see if + # a pattern for refactoring emerges in the future, but for now I'll leave + # this as-is. + def upsert_configs + @configs.each do |key, value| + if key == "auth_providers_to_enable" + update_enabled_providers(value) unless value.class.name != "String" + elsif value.is_a?(Array) && value.any? + Settings::Authentication.public_send("#{key}=", value.reject(&:blank?)) + elsif value.present? + Settings::Authentication.public_send("#{key}=", value.strip) + end + rescue ActiveRecord::RecordInvalid => e + @errors << e.message + next + end + end + + def update_enabled_providers(value) + enabled_providers = value.split(",").filter_map do |entry| + entry unless invalid_provider_entry(entry) + end + return if email_login_disabled_with_one_or_less_auth_providers(enabled_providers) + + Settings::Authentication.providers = enabled_providers + end + + def invalid_provider_entry(entry) + entry.blank? || + Authentication::Providers.available.map(&:to_s).exclude?(entry) || + provider_keys_missing(entry) + end + + def provider_keys_missing(entry) + Settings::Authentication.public_send("#{entry}_key").blank? || + Settings::Authentication.public_send("#{entry}_secret").blank? + end + + def email_login_disabled_with_one_or_less_auth_providers(enabled_providers) + !Settings::Authentication.allow_email_password_login && + enabled_providers.count <= 1 + end + end +end diff --git a/app/services/github/oauth_client.rb b/app/services/github/oauth_client.rb index 1cdd53280..b629b58de 100644 --- a/app/services/github/oauth_client.rb +++ b/app/services/github/oauth_client.rb @@ -7,8 +7,8 @@ module Github # @param credentials [Hash] the OAuth credentials, {client_id:, client_secret:} or {access_token:} def initialize(credentials = nil) credentials ||= { - client_id: SiteConfig.github_key, - client_secret: SiteConfig.github_secret + client_id: Settings::Authentication.github_key, + client_secret: Settings::Authentication.github_secret } @credentials = check_credentials!(credentials) end diff --git a/app/services/re_captcha/check_enabled.rb b/app/services/re_captcha/check_enabled.rb index 2151b5393..03a42e558 100644 --- a/app/services/re_captcha/check_enabled.rb +++ b/app/services/re_captcha/check_enabled.rb @@ -31,7 +31,8 @@ module ReCaptcha private def keys_configured? - SiteConfig.recaptcha_site_key.present? && SiteConfig.recaptcha_secret_key.present? + Settings::Authentication.recaptcha_site_key.present? && + Settings::Authentication.recaptcha_secret_key.present? end end end diff --git a/app/services/re_captcha/check_registration_enabled.rb b/app/services/re_captcha/check_registration_enabled.rb index cace7f521..51a892b5a 100644 --- a/app/services/re_captcha/check_registration_enabled.rb +++ b/app/services/re_captcha/check_registration_enabled.rb @@ -1,13 +1,10 @@ module ReCaptcha class CheckRegistrationEnabled def self.call - new.call - end - - def call # ReCaptcha::CheckEnabled.call without a user parameter will return `true` # if the ReCaptcha SiteConfig keys are configured, and `false` otherwise - ReCaptcha::CheckEnabled.call && SiteConfig.require_captcha_for_email_password_registration + ReCaptcha::CheckEnabled.call && + Settings::Authentication.require_captcha_for_email_password_registration end end end diff --git a/app/services/site_configs/upsert.rb b/app/services/settings/upsert.rb similarity index 63% rename from app/services/site_configs/upsert.rb rename to app/services/settings/upsert.rb index 852beb399..7cc6526af 100644 --- a/app/services/site_configs/upsert.rb +++ b/app/services/settings/upsert.rb @@ -1,4 +1,4 @@ -module SiteConfigs +module Settings class Upsert EMOJI_ONLY_FIELDS = %w[community_emoji].freeze VALID_DOMAIN = /^[a-zA-Z0-9]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/.freeze @@ -34,9 +34,7 @@ module SiteConfigs def upsert_configs @configs.each do |key, value| - if key == "auth_providers_to_enable" - update_enabled_auth_providers(value) unless value.class.name != "String" - elsif value.is_a?(Array) + if value.is_a?(Array) SiteConfig.public_send("#{key}=", value.reject(&:blank?)) unless value.empty? elsif value.respond_to?(:to_h) SiteConfig.public_send("#{key}=", value.to_h) unless value.empty? @@ -60,27 +58,6 @@ module SiteConfigs @configs[:credit_prices_in_cents]&.transform_values!(&:to_i) end - def update_enabled_auth_providers(value) - enabled_providers = value.split(",").filter_map do |entry| - entry unless invalid_provider_entry(entry) - end - SiteConfig.public_send("authentication_providers=", enabled_providers) unless - email_login_disabled_with_one_or_less_auth_providers(enabled_providers) - end - - def email_login_disabled_with_one_or_less_auth_providers(enabled_providers) - !SiteConfig.allow_email_password_login && enabled_providers.count <= 1 - end - - def invalid_provider_entry(entry) - entry.blank? || Authentication::Providers.available.map(&:to_s).exclude?(entry) || - provider_keys_missing(entry) - end - - def provider_keys_missing(entry) - SiteConfig.public_send("#{entry}_key").blank? || SiteConfig.public_send("#{entry}_secret").blank? - end - def create_tags_if_not_created # Bulk create tags if they should exist. # This is an acts-as-taggable-on as used on saving of an Article, etc. diff --git a/app/services/twitter_client/client.rb b/app/services/twitter_client/client.rb index c5c5d0fa8..fc03c6c4b 100644 --- a/app/services/twitter_client/client.rb +++ b/app/services/twitter_client/client.rb @@ -57,8 +57,8 @@ module TwitterClient def target Twitter::REST::Client.new( - consumer_key: SiteConfig.twitter_key.presence || ApplicationConfig["TWITTER_KEY"], - consumer_secret: SiteConfig.twitter_secret.presence || ApplicationConfig["TWITTER_SECRET"], + consumer_key: Settings::Authentication.twitter_key.presence || ApplicationConfig["TWITTER_KEY"], + consumer_secret: Settings::Authentication.twitter_secret.presence || ApplicationConfig["TWITTER_SECRET"], user_agent: "TwitterRubyGem/#{Twitter::Version} (#{URL.url})", timeouts: { connect: 5, diff --git a/app/views/admin/configs/_apple_auth_provider_settings.html.erb b/app/views/admin/configs/_apple_auth_provider_settings.html.erb index 51db996c0..ce5c858db 100644 --- a/app/views/admin/configs/_apple_auth_provider_settings.html.erb +++ b/app/views/admin/configs/_apple_auth_provider_settings.html.erb @@ -11,42 +11,42 @@ requires a custom partial
<%= admin_config_label :apple_client_id %>

- <%= Constants::SiteConfig::DETAILS[:apple_client_id][:description] %> + <%= Constants::Settings::Authentication::DETAILS[:apple_client_id][:description] %>

<%= f.text_field :apple_client_id, class: "crayons-textfield", - value: SiteConfig.apple_client_id, - placeholder: Constants::SiteConfig::DETAILS[:apple_client_id][:placeholder] %> + value: Settings::Authentication.apple_client_id, + placeholder: Constants::Settings::Authentication::DETAILS[:apple_client_id][:placeholder] %>
<%= admin_config_label :apple_key_id %>

- <%= Constants::SiteConfig::DETAILS[:apple_key_id][:description] %> + <%= Constants::Settings::Authentication::DETAILS[:apple_key_id][:description] %>

<%= f.text_field :apple_key_id, class: "crayons-textfield", - value: SiteConfig.apple_key_id, - placeholder: Constants::SiteConfig::DETAILS[:apple_key_id][:placeholder] %> + value: Settings::Authentication.apple_key_id, + placeholder: Constants::Settings::Authentication::DETAILS[:apple_key_id][:placeholder] %>

<%= admin_config_label :apple_pem %>

- <%= Constants::SiteConfig::DETAILS[:apple_pem][:description] %> + <%= Constants::Settings::Authentication::DETAILS[:apple_pem][:description] %>

<%= f.text_field :apple_pem, class: "crayons-textfield", - value: SiteConfig.apple_pem, - placeholder: Constants::SiteConfig::DETAILS[:apple_pem][:placeholder] %> + value: Settings::Authentication.apple_pem, + placeholder: Constants::Settings::Authentication::DETAILS[:apple_pem][:placeholder] %>

<%= admin_config_label :apple_team_id %>

- <%= Constants::SiteConfig::DETAILS[:apple_team_id][:description] %> + <%= Constants::Settings::Authentication::DETAILS[:apple_team_id][:description] %>

<%= f.text_field :apple_team_id, class: "crayons-textfield", - value: SiteConfig.apple_team_id, - placeholder: Constants::SiteConfig::DETAILS[:apple_team_id][:placeholder] %> + value: Settings::Authentication.apple_team_id, + placeholder: Constants::Settings::Authentication::DETAILS[:apple_team_id][:placeholder] %>

<% if authentication_provider_enabled?(provider) %> diff --git a/app/views/admin/configs/_auth_provider_settings.html.erb b/app/views/admin/configs/_auth_provider_settings.html.erb index 4f9698fdc..c79ac3c1e 100644 --- a/app/views/admin/configs/_auth_provider_settings.html.erb +++ b/app/views/admin/configs/_auth_provider_settings.html.erb @@ -2,22 +2,22 @@
<%= admin_config_label :"#{provider.provider_name}_key" %>

- <%= Constants::SiteConfig::DETAILS[:"#{provider.provider_name}_key"][:description] %> + <%= Constants::Settings::Authentication::DETAILS[:"#{provider.provider_name}_key"][:description] %>

<%= f.text_field :"#{provider.provider_name}_key", class: "crayons-textfield", - value: SiteConfig.public_send("#{provider.provider_name}_key"), - placeholder: Constants::SiteConfig::DETAILS[:"#{provider.provider_name}_key"][:placeholder] %> + value: Settings::Authentication.public_send("#{provider.provider_name}_key"), + placeholder: Constants::Settings::Authentication::DETAILS[:"#{provider.provider_name}_key"][:placeholder] %>
<%= admin_config_label :"#{provider.provider_name}_secret" %>

- <%= Constants::SiteConfig::DETAILS[:"#{provider.provider_name}_secret"][:description] %> + <%= Constants::Settings::Authentication::DETAILS[:"#{provider.provider_name}_secret"][:description] %>

<%= f.text_field :"#{provider.provider_name}_secret", class: "crayons-textfield", - value: SiteConfig.public_send("#{provider.provider_name}_secret"), - placeholder: Constants::SiteConfig::DETAILS[:"#{provider.provider_name}_secret"][:placeholder] %> + value: Settings::Authentication.public_send("#{provider.provider_name}_secret"), + placeholder: Constants::Settings::Authentication::DETAILS[:"#{provider.provider_name}_secret"][:placeholder] %>

<% if authentication_provider_enabled?(provider) %> diff --git a/app/views/admin/configs/show.html.erb b/app/views/admin/configs/show.html.erb index 17255a575..b5192c8ad 100644 --- a/app/views/admin/configs/show.html.erb +++ b/app/views/admin/configs/show.html.erb @@ -147,7 +147,7 @@
<% end %> - <%= form_for(SiteConfig.new, url: admin_config_path, html: { data: { action: "submit->config#configUpdatePrecheck", "config-target": "authSectionForm", testid: "authSectionForm" } }) do |f| %> + <%= form_for(Settings::Authentication.new, url: admin_settings_authentications_path, html: { data: { action: "submit->config#configUpdatePrecheck", "config-target": "authSectionForm", testid: "authSectionForm" } }) do |f| %>
<%= render partial: "admin/shared/card_header", locals: { @@ -166,11 +166,11 @@ data-tooltip="Unchecking this will enable Email Registration"> <%= f.check_box :invite_only_mode, checked: invite_only_mode_or_no_enabled_auth_options, - data: { action: "config#adjustAuthenticationOptions", target: "config.inviteOnlyMode" }, + data: { action: "config#adjustAuthenticationOptions", "config-target": "inviteOnlyMode" }, class: "crayons-checkbox" %>
- <%= admin_config_label :invite_only_mode, "Invite-only mode" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:invite_only_mode][:description] %> + <%= admin_config_label :invite_only_mode, "Invite-only mode", model: Settings::Authentication %> + <%= admin_config_description Constants::Settings::Authentication::DETAILS[:invite_only_mode][:description] %>
@@ -194,11 +194,11 @@ data-tooltip="<%= tooltip_text_email_or_auth_provider_btns %>">
-

"> +

"> Email address

" + class="enabled-indicator <%= Settings::Authentication.allow_email_password_registration ? "visible" : "" %>" data-config-target="enabledIndicator"> <%= inline_svg_tag("checkmark.svg", aria: true, class: "crayons-icon admin-config-checkmark", title: "Email enabled") %> Enabled @@ -208,11 +208,11 @@
@@ -220,67 +220,67 @@
- <%= admin_config_label :allowed_registration_email_domains, "Allowed email domains" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:allowed_registration_email_domains][:description] %> + <%= admin_config_label :allowed_registration_email_domains, "Allowed email domains", model: Settings::Authentication %> + <%= admin_config_description Constants::Settings::Authentication::DETAILS[:allowed_registration_email_domains][:description] %> <%= f.text_field :allowed_registration_email_domains, class: "crayons-textfield", - value: SiteConfig.allowed_registration_email_domains.join(","), - placeholder: Constants::SiteConfig::DETAILS[:allowed_registration_email_domains][:placeholder] %> + value: Settings::Authentication.allowed_registration_email_domains.join(","), + placeholder: Constants::Settings::Authentication::DETAILS[:allowed_registration_email_domains][:placeholder] %>
<%= f.check_box :display_email_domain_allow_list_publicly, - checked: SiteConfig.display_email_domain_allow_list_publicly, + checked: Settings::Authentication.display_email_domain_allow_list_publicly, id: "email-display-emails-publicly-checkbox", class: "crayons-checkbox mt-2" %>
- <%= admin_config_label :display_email_domain_allow_list_publicly %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:display_email_domain_allow_list_publicly][:description] %> + <%= admin_config_label :display_email_domain_allow_list_publicly, model: Settings::Authentication %> + <%= admin_config_description Constants::Settings::Authentication::DETAILS[:display_email_domain_allow_list_publicly][:description] %>
<%= f.check_box :require_captcha_for_email_password_registration, - checked: SiteConfig.require_captcha_for_email_password_registration, + checked: Settings::Authentication.require_captcha_for_email_password_registration, data: { action: "config#toggleGoogleRecaptchaFields", "config-target": "requireCaptchaForEmailPasswordRegistration" }, class: "crayons-checkbox mt-2" %>
- <%= admin_config_label :require_captcha_for_email_password_registration, "Enable Google reCAPTCHA for email password registration" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:require_captcha_for_email_password_registration][:description] %> + <%= admin_config_label :require_captcha_for_email_password_registration, "Enable Google reCAPTCHA for email password registration", model: Settings::Authentication %> + <%= admin_config_description Constants::Settings::Authentication::DETAILS[:require_captcha_for_email_password_registration][:description] %>
-
" aria-labelledby="recaptchaContainer"> +
" aria-labelledby="recaptchaContainer">
- <%= admin_config_label :recaptcha_site_key, "Google reCAPTCHA site key" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:recaptcha_site_key][:description] %> + <%= admin_config_label :recaptcha_site_key, "Google reCAPTCHA site key", model: Settings::Authentication %> + <%= admin_config_description Constants::Settings::Authentication::DETAILS[:recaptcha_site_key][:description] %> <%= f.text_field :recaptcha_site_key, class: "crayons-textfield", - value: SiteConfig.recaptcha_site_key, - placeholder: Constants::SiteConfig::DETAILS[:recaptcha_site_key][:placeholder] %> + value: Settings::Authentication.recaptcha_site_key, + placeholder: Constants::Settings::Authentication::DETAILS[:recaptcha_site_key][:placeholder] %>
- <%= admin_config_label :recaptcha_secret_key, "Google reCAPTCHA secret key" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:recaptcha_secret_key][:description] %> + <%= admin_config_label :recaptcha_secret_key, "Google reCAPTCHA secret key", model: Settings::Authentication %> + <%= admin_config_description Constants::Settings::Authentication::DETAILS[:recaptcha_secret_key][:description] %> <%= f.text_field :recaptcha_secret_key, class: "crayons-textfield", - value: SiteConfig.recaptcha_secret_key, - placeholder: Constants::SiteConfig::DETAILS[:recaptcha_secret_key][:placeholder] %> + value: Settings::Authentication.recaptcha_secret_key, + placeholder: Constants::Settings::Authentication::DETAILS[:recaptcha_secret_key][:placeholder] %>
- <% if SiteConfig.allow_email_password_registration %> + <% if Settings::Authentication.allow_email_password_registration %> -
<% authentication_available_providers.each do |provider| %> @@ -319,7 +319,7 @@ data-tooltip="<%= tooltip_text_email_or_auth_provider_btns %>">

"> - <%= provider.official_name %> + <%= provider.official_name %>

-
-
-
- <%= admin_config_label :campaign_hero_html_variant_name, "Campaign hero HTML variant name" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_hero_html_variant_name][:description] %> - <%= f.text_field :campaign_hero_html_variant_name, - class: "crayons-textfield", - value: SiteConfig.campaign_hero_html_variant_name, - placeholder: Constants::SiteConfig::DETAILS[:campaign_hero_html_variant_name][:placeholder] %> -
+
+
+
+ <%= admin_config_label :campaign_hero_html_variant_name, "Campaign hero HTML variant name" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_hero_html_variant_name][:description] %> + <%= f.text_field :campaign_hero_html_variant_name, + class: "crayons-textfield", + value: SiteConfig.campaign_hero_html_variant_name, + placeholder: Constants::SiteConfig::DETAILS[:campaign_hero_html_variant_name][:placeholder] %> +
-
- <%= f.check_box :campaign_articles_require_approval, checked: SiteConfig.campaign_articles_require_approval, class: "crayons-checkbox" %> - <%= admin_config_label :campaign_articles_require_approval %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_articles_require_approval][:description] %> -
+
+ <%= f.check_box :campaign_articles_require_approval, checked: SiteConfig.campaign_articles_require_approval, class: "crayons-checkbox" %> + <%= admin_config_label :campaign_articles_require_approval %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_articles_require_approval][:description] %> +
-
- <%= f.check_box :campaign_sidebar_enabled, checked: SiteConfig.campaign_sidebar_enabled, class: "crayons-checkbox" %> - <%= admin_config_label :campaign_sidebar_enabled %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_sidebar_enabled][:description] %> -
+
+ <%= f.check_box :campaign_sidebar_enabled, checked: SiteConfig.campaign_sidebar_enabled, class: "crayons-checkbox" %> + <%= admin_config_label :campaign_sidebar_enabled %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_sidebar_enabled][:description] %> +
-
- <%= admin_config_label :campaign_sidebar_image %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_sidebar_image][:description] %> - <% if SiteConfig.campaign_sidebar_image.present? %> -
-
- Campaign sidebar image -
+
+ <%= admin_config_label :campaign_sidebar_image %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_sidebar_image][:description] %> + <% if SiteConfig.campaign_sidebar_image.present? %> +
+
+ Campaign sidebar image
- <% end %> - <%= f.text_field :campaign_sidebar_image, +
+ <% end %> + <%= f.text_field :campaign_sidebar_image, + class: "crayons-textfield", + value: SiteConfig.campaign_sidebar_image, + placeholder: Constants::SiteConfig::DETAILS[:campaign_sidebar_image][:placeholder] %> +
+ +
+ <%= admin_config_label :campaign_url, "Campaign URL" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_url][:description] %> + <%= f.text_field :campaign_url, + class: "crayons-textfield", + value: SiteConfig.campaign_url, + placeholder: Constants::SiteConfig::DETAILS[:campaign_url][:placeholder] %> +
+ +
+ <%= admin_config_label :campaign_featured_tags %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_featured_tags][:description] %> + <%= f.text_field :campaign_featured_tags, + class: "crayons-textfield", + value: SiteConfig.campaign_featured_tags.join(","), + placeholder: Constants::SiteConfig::DETAILS[:campaign_featured_tags][:placeholder] %> +
+ +
+ <%= admin_config_label :campaign_call_to_action, "Campaign Call to Action" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_call_to_action][:description] %> + <%= f.text_field :campaign_call_to_action, + class: "crayons-textfield", + value: SiteConfig.campaign_call_to_action, + placeholder: Constants::SiteConfig::DETAILS[:campaign_call_to_action][:placeholder] %> +
+ +
+ <%= admin_config_label :campaign_articles_expiry_time, "Campaign article expiry time" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_articles_expiry_time][:description] %> + <%= f.number_field :campaign_articles_expiry_time, class: "crayons-textfield", - value: SiteConfig.campaign_sidebar_image, - placeholder: Constants::SiteConfig::DETAILS[:campaign_sidebar_image][:placeholder] %> -
+ value: SiteConfig.campaign_articles_expiry_time, + placeholder: Constants::SiteConfig::DETAILS[:campaign_articles_expiry_time][:placeholder] %> +
-
- <%= admin_config_label :campaign_url, "Campaign URL" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_url][:description] %> - <%= f.text_field :campaign_url, - class: "crayons-textfield", - value: SiteConfig.campaign_url, - placeholder: Constants::SiteConfig::DETAILS[:campaign_url][:placeholder] %> -
- -
- <%= admin_config_label :campaign_featured_tags %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_featured_tags][:description] %> - <%= f.text_field :campaign_featured_tags, - class: "crayons-textfield", - value: SiteConfig.campaign_featured_tags.join(","), - placeholder: Constants::SiteConfig::DETAILS[:campaign_featured_tags][:placeholder] %> -
- -
- <%= admin_config_label :campaign_call_to_action, "Campaign Call to Action" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_call_to_action][:description] %> - <%= f.text_field :campaign_call_to_action, - class: "crayons-textfield", - value: SiteConfig.campaign_call_to_action, - placeholder: Constants::SiteConfig::DETAILS[:campaign_call_to_action][:placeholder] %> -
- -
- <%= admin_config_label :campaign_articles_expiry_time, "Campaign article expiry time" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:campaign_articles_expiry_time][:description] %> - <%= f.number_field :campaign_articles_expiry_time, - class: "crayons-textfield", - value: SiteConfig.campaign_articles_expiry_time, - placeholder: Constants::SiteConfig::DETAILS[:campaign_articles_expiry_time][:placeholder] %> -
- - <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -462,91 +462,91 @@ target: "contentBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :community_name %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:community_name][:description] %> - <%= f.text_field :community_name, - class: "crayons-textfield", - value: SiteConfig.community_name, - placeholder: Constants::SiteConfig::DETAILS[:community_name][:placeholder] %> -
+
+
+
+ <%= admin_config_label :community_name %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:community_name][:description] %> + <%= f.text_field :community_name, + class: "crayons-textfield", + value: SiteConfig.community_name, + placeholder: Constants::SiteConfig::DETAILS[:community_name][:placeholder] %> +
-
- <%= admin_config_label :community_emoji %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:community_emoji][:description] %> - <%= f.text_field :community_emoji, - class: "crayons-textfield", - value: SiteConfig.community_emoji, - placeholder: Constants::SiteConfig::DETAILS[:community_emoji][:placeholder] %> -
+
+ <%= admin_config_label :community_emoji %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:community_emoji][:description] %> + <%= f.text_field :community_emoji, + class: "crayons-textfield", + value: SiteConfig.community_emoji, + placeholder: Constants::SiteConfig::DETAILS[:community_emoji][:placeholder] %> +
-
- <%= admin_config_label :tagline %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:tagline][:description] %> - <%= f.text_field :tagline, - class: "crayons-textfield", - value: SiteConfig.tagline, - placeholder: Constants::SiteConfig::DETAILS[:tagline][:placeholder] %> -
+
+ <%= admin_config_label :tagline %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:tagline][:description] %> + <%= f.text_field :tagline, + class: "crayons-textfield", + value: SiteConfig.tagline, + placeholder: Constants::SiteConfig::DETAILS[:tagline][:placeholder] %> +
-
- <%= admin_config_label :community_description %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:community_description][:description] %> - <%= f.text_field :community_description, - class: "crayons-textfield", - value: SiteConfig.community_description, - placeholder: Constants::SiteConfig::DETAILS[:community_description][:placeholder] %> -
+
+ <%= admin_config_label :community_description %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:community_description][:description] %> + <%= f.text_field :community_description, + class: "crayons-textfield", + value: SiteConfig.community_description, + placeholder: Constants::SiteConfig::DETAILS[:community_description][:placeholder] %> +
-
- <%= admin_config_label :community_member_label %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:community_member_label][:description] %> - <%= f.text_field :community_member_label, - class: "crayons-textfield", - value: SiteConfig.community_member_label, - placeholder: Constants::SiteConfig::DETAILS[:community_member_label][:placeholder] %> -
+
+ <%= admin_config_label :community_member_label %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:community_member_label][:description] %> + <%= f.text_field :community_member_label, + class: "crayons-textfield", + value: SiteConfig.community_member_label, + placeholder: Constants::SiteConfig::DETAILS[:community_member_label][:placeholder] %> +
-
- <%= admin_config_label :community_copyright_start_year %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:community_copyright_start_year][:description] %> - <%= f.text_field :community_copyright_start_year, - class: "crayons-textfield", - value: SiteConfig.community_copyright_start_year, - placeholder: Constants::SiteConfig::DETAILS[:community_copyright_start_year][:placeholder] %> -
+
+ <%= admin_config_label :community_copyright_start_year %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:community_copyright_start_year][:description] %> + <%= f.text_field :community_copyright_start_year, + class: "crayons-textfield", + value: SiteConfig.community_copyright_start_year, + placeholder: Constants::SiteConfig::DETAILS[:community_copyright_start_year][:placeholder] %> +
-
- <%= admin_config_label :staff_user_id %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:staff_user_id][:description] %> - <%= f.text_field :staff_user_id, - class: "crayons-textfield", - value: SiteConfig.staff_user_id, - placeholder: Constants::SiteConfig::DETAILS[:staff_user_id][:placeholder] %> -
+
+ <%= admin_config_label :staff_user_id %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:staff_user_id][:description] %> + <%= f.text_field :staff_user_id, + class: "crayons-textfield", + value: SiteConfig.staff_user_id, + placeholder: Constants::SiteConfig::DETAILS[:staff_user_id][:placeholder] %> +
-
- <%= admin_config_label :experience_low %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:experience_low][:description] %> - <%= f.text_field :experience_low, - class: "crayons-texfield", - value: SiteConfig.experience_low, - placeholder: Constants::SiteConfig::DETAILS[:experience_low][:placeholder] %> -
+
+ <%= admin_config_label :experience_low %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:experience_low][:description] %> + <%= f.text_field :experience_low, + class: "crayons-texfield", + value: SiteConfig.experience_low, + placeholder: Constants::SiteConfig::DETAILS[:experience_low][:placeholder] %> +
-
- <%= admin_config_label :experience_high %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:experience_high][:description] %> - <%= f.text_field :experience_high, - class: "crayons-texfield", - value: SiteConfig.experience_high, - placeholder: Constants::SiteConfig::DETAILS[:experience_high][:placeholder] %> -
- <%= render "form_submission", f: f %> -
-
+
+ <%= admin_config_label :experience_high %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:experience_high][:description] %> + <%= f.text_field :experience_high, + class: "crayons-texfield", + value: SiteConfig.experience_high, + placeholder: Constants::SiteConfig::DETAILS[:experience_high][:placeholder] %> +
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -560,44 +560,44 @@ expanded: false } %> -
-
- <%= f.fields_for :credit_prices_in_cents do |price_field| %> -
- <%= admin_config_label "Credit price in cents (S)" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:small][:description] %> - <%= price_field.number_field :small, - class: "crayons-textfield", - value: SiteConfig.credit_prices_in_cents[:small] %> -
+
+
+ <%= f.fields_for :credit_prices_in_cents do |price_field| %> +
+ <%= admin_config_label "Credit price in cents (S)" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:small][:description] %> + <%= price_field.number_field :small, + class: "crayons-textfield", + value: SiteConfig.credit_prices_in_cents[:small] %> +
-
- <%= admin_config_label "Credit price in cents (M)" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:medium][:description] %> - <%= price_field.number_field :medium, - class: "crayons-textfield", - value: SiteConfig.credit_prices_in_cents[:medium] %> -
-
- <%= admin_config_label "Credit price in cents (L)" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:large][:description] %> - <%= price_field.number_field :large, - class: "crayons-textfield", - value: SiteConfig.credit_prices_in_cents[:large] %> -
+
+ <%= admin_config_label "Credit price in cents (M)" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:medium][:description] %> + <%= price_field.number_field :medium, + class: "crayons-textfield", + value: SiteConfig.credit_prices_in_cents[:medium] %> +
+
+ <%= admin_config_label "Credit price in cents (L)" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:large][:description] %> + <%= price_field.number_field :large, + class: "crayons-textfield", + value: SiteConfig.credit_prices_in_cents[:large] %> +
-
- <%= admin_config_label "Credit price in cents (XL)" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:xlarge][:description] %> - <%= price_field.number_field :xlarge, - class: "crayons-textfield", - value: SiteConfig.credit_prices_in_cents[:xlarge] %> -
- <% end %> +
+ <%= admin_config_label "Credit price in cents (XL)" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:credit_prices_in_cents][:xlarge][:description] %> + <%= price_field.number_field :xlarge, + class: "crayons-textfield", + value: SiteConfig.credit_prices_in_cents[:xlarge] %> +
+ <% end %> - <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -610,59 +610,32 @@ target: "emailBodyContainer", expanded: false } %> -
-
-
- -
- Default (set via default_email environment variable) -
- " class="form-control" readonly> -
- <%= f.fields_for :email_addresses do |email_field| %> - <% SiteConfig.email_addresses.except(:default).each do |type, address| %> -
- <%= admin_config_label type %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:email_addresses][:description] %> - <%= email_field.text_field type, - class: "crayons-textfield", - value: SiteConfig.email_addresses[type], - placeholder: Constants::SiteConfig::DETAILS[:email_addresses][:placeholder] %> -
- <% end %> - <% end %> - - <%= render "form_submission", f: f %> -
-
-
- <% end %> - - <%= form_for(SiteConfig.new, url: admin_config_path) do |f| %> -
- <%= render partial: "admin/shared/card_header", - locals: { - header: "Email digest frequency", - state: "collapse", - target: "emailDigestBodyContainer", - expanded: false - } %> -
-
-
- <%= admin_config_label :periodic_email_digest %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:periodic_email_digest][:description] %> - <%= f.number_field :periodic_email_digest, - class: "crayons-textfield", - value: SiteConfig.periodic_email_digest, - placeholder: Constants::SiteConfig::DETAILS[:periodic_email_digest][:placeholder] %> +
+
+
+ +
+ Default (set via default_email environment variable)
+ " class="form-control" readonly> +
+ <%= f.fields_for :email_addresses do |email_field| %> + <% SiteConfig.email_addresses.except(:default).each do |type, address| %> +
+ <%= admin_config_label type %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:email_addresses][:description] %> + <%= email_field.text_field type, + class: "crayons-textfield", + value: SiteConfig.email_addresses[type], + placeholder: Constants::SiteConfig::DETAILS[:email_addresses][:placeholder] %> +
+ <% end %> + <% end %> - <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
<% end %> @@ -675,27 +648,27 @@ target: "jobsBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :jobs_url, "Jobs URL" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:jobs_url][:description] %> - <%= f.text_field :jobs_url, - class: "crayons-textfield", - value: SiteConfig.jobs_url, - placeholder: Constants::SiteConfig::DETAILS[:jobs_url][:placeholder] %> -
-
- <%= f.check_box :display_jobs_banner, checked: SiteConfig.display_jobs_banner, class: "crayons-checkbox" %> -
- <%= admin_config_label :display_jobs_banner %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:display_jobs_banner][:description] %> -
+
+
+
+ <%= admin_config_label :jobs_url, "Jobs URL" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:jobs_url][:description] %> + <%= f.text_field :jobs_url, + class: "crayons-textfield", + value: SiteConfig.jobs_url, + placeholder: Constants::SiteConfig::DETAILS[:jobs_url][:placeholder] %> +
+
+ <%= f.check_box :display_jobs_banner, checked: SiteConfig.display_jobs_banner, class: "crayons-checkbox" %> +
+ <%= admin_config_label :display_jobs_banner %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:display_jobs_banner][:description] %>
+
- <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -708,19 +681,19 @@ target: "gaBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :ga_tracking_id, "View ID" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:ga_tracking_id][:description] %> - <%= f.text_field :ga_tracking_id, - class: "crayons-textfield", - value: SiteConfig.ga_tracking_id %> -
+
+
+
+ <%= admin_config_label :ga_tracking_id, "View ID" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:ga_tracking_id][:description] %> + <%= f.text_field :ga_tracking_id, + class: "crayons-textfield", + value: SiteConfig.ga_tracking_id %> +
- <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -733,72 +706,72 @@ target: "imagesBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :main_social_image %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:main_social_image][:description] %> - <%= f.text_field :main_social_image, - class: "crayons-textfield", - value: SiteConfig.main_social_image, - placeholder: Constants::SiteConfig::DETAILS[:main_social_image][:placeholder] %> - <% if SiteConfig.main_social_image.present? %> - main social image - <% end %> -
+
+
+
+ <%= admin_config_label :main_social_image %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:main_social_image][:description] %> + <%= f.text_field :main_social_image, + class: "crayons-textfield", + value: SiteConfig.main_social_image, + placeholder: Constants::SiteConfig::DETAILS[:main_social_image][:placeholder] %> + <% if SiteConfig.main_social_image.present? %> + main social image + <% end %> +
-
- <%= admin_config_label :favicon_url, "Favicon URL" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:favicon_url][:description] %> - <%= f.text_field :favicon_url, - class: "form-control", - value: SiteConfig.favicon_url, - placeholder: Constants::SiteConfig::DETAILS[:favicon_url][:placeholder] %> - favicon -
+
+ <%= admin_config_label :favicon_url, "Favicon URL" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:favicon_url][:description] %> + <%= f.text_field :favicon_url, + class: "form-control", + value: SiteConfig.favicon_url, + placeholder: Constants::SiteConfig::DETAILS[:favicon_url][:placeholder] %> + favicon +
-
- <%= admin_config_label :logo_png %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:logo_png][:description] %> - <%= f.text_field :logo_png, - class: "crayons-textfield", - value: SiteConfig.logo_png, - placeholder: Constants::SiteConfig::DETAILS[:logo_png][:placeholder] %> - <% if SiteConfig.logo_png.present? %> - - <% end %> -
+
+ <%= admin_config_label :logo_png %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:logo_png][:description] %> + <%= f.text_field :logo_png, + class: "crayons-textfield", + value: SiteConfig.logo_png, + placeholder: Constants::SiteConfig::DETAILS[:logo_png][:placeholder] %> + <% if SiteConfig.logo_png.present? %> + + <% end %> +
-
- <%= admin_config_label :logo_svg %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:logo_svg][:description] %> - <%= f.text_area :logo_svg, - class: "crayons-textfield", - value: SiteConfig.logo_svg, - rows: 6, - placeholder: Constants::SiteConfig::DETAILS[:logo_svg][:placeholder] %> - <% if SiteConfig.logo_svg.present? %> - - <% end %> -
+
+ <%= admin_config_label :logo_svg %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:logo_svg][:description] %> + <%= f.text_area :logo_svg, + class: "crayons-textfield", + value: SiteConfig.logo_svg, + rows: 6, + placeholder: Constants::SiteConfig::DETAILS[:logo_svg][:placeholder] %> + <% if SiteConfig.logo_svg.present? %> + + <% end %> +
-
- <%= admin_config_label :secondary_logo_url %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:secondary_logo_url][:description] %> - <%= f.text_field :secondary_logo_url, - class: "crayons-textfield", - value: SiteConfig.secondary_logo_url, - placeholder: Constants::SiteConfig::DETAILS[:secondary_logo_url][:placeholder] %> - <% if SiteConfig.secondary_logo_url.present? %> - secondary logo image - <% end %> -
+
+ <%= admin_config_label :secondary_logo_url %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:secondary_logo_url][:description] %> + <%= f.text_field :secondary_logo_url, + class: "crayons-textfield", + value: SiteConfig.secondary_logo_url, + placeholder: Constants::SiteConfig::DETAILS[:secondary_logo_url][:placeholder] %> + <% if SiteConfig.secondary_logo_url.present? %> + secondary logo image + <% end %> +
- <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -811,72 +784,72 @@ target: "mascotBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :mascot_user_id, "Mascot user ID" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_user_id][:description] %> - <%= f.text_field :mascot_user_id, - class: "crayons-textfield", - value: SiteConfig.mascot_user_id, - min: 1, - placeholder: Constants::SiteConfig::DETAILS[:mascot_user_id][:placeholder] %> -
- -
- <%= admin_config_label :mascot_image_url, "Mascot Image URL" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_image_url][:description] %> - <%= f.text_field :mascot_image_url, - class: "crayons-textfield", - value: SiteConfig.mascot_image_url, - placeholder: Constants::SiteConfig::DETAILS[:mascot_image_url][:placeholder] %> - -
- <%= SiteConfig.mascot_image_description %> -
- -
- -
- <%= admin_config_label :mascot_footer_image_url %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_url][:description] %> - <%= f.text_field :mascot_footer_image_url, - class: "crayons-textfield", - value: SiteConfig.mascot_footer_image_url, - placeholder: Constants::SiteConfig::DETAILS[:mascot_footer_image_url][:placeholder] %> - -
- <%= SiteConfig.mascot_image_description %> -
-
- -
- <%= admin_config_label :mascot_footer_image_width %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_width][:description] %> - <%= f.text_field :mascot_footer_image_width, - class: "form-control", - value: SiteConfig.mascot_footer_image_width %> -
- -
- <%= admin_config_label :mascot_footer_image_height %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_height][:description] %> - <%= f.text_field :mascot_footer_image_height, - class: "form-control", - value: SiteConfig.mascot_footer_image_height %> -
- -
- <%= admin_config_label :mascot_image_description %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_image_description][:description] %> - <%= f.text_field :mascot_image_description, - class: "form-control", - value: SiteConfig.mascot_image_description %> -
- - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :mascot_user_id, "Mascot user ID" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_user_id][:description] %> + <%= f.text_field :mascot_user_id, + class: "crayons-textfield", + value: SiteConfig.mascot_user_id, + min: 1, + placeholder: Constants::SiteConfig::DETAILS[:mascot_user_id][:placeholder] %>
+ +
+ <%= admin_config_label :mascot_image_url, "Mascot Image URL" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_image_url][:description] %> + <%= f.text_field :mascot_image_url, + class: "crayons-textfield", + value: SiteConfig.mascot_image_url, + placeholder: Constants::SiteConfig::DETAILS[:mascot_image_url][:placeholder] %> + +
+ <%= SiteConfig.mascot_image_description %> +
+ +
+ +
+ <%= admin_config_label :mascot_footer_image_url %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_url][:description] %> + <%= f.text_field :mascot_footer_image_url, + class: "crayons-textfield", + value: SiteConfig.mascot_footer_image_url, + placeholder: Constants::SiteConfig::DETAILS[:mascot_footer_image_url][:placeholder] %> + +
+ <%= SiteConfig.mascot_image_description %> +
+
+ +
+ <%= admin_config_label :mascot_footer_image_width %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_width][:description] %> + <%= f.text_field :mascot_footer_image_width, + class: "form-control", + value: SiteConfig.mascot_footer_image_width %> +
+ +
+ <%= admin_config_label :mascot_footer_image_height %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_footer_image_height][:description] %> + <%= f.text_field :mascot_footer_image_height, + class: "form-control", + value: SiteConfig.mascot_footer_image_height %> +
+ +
+ <%= admin_config_label :mascot_image_description %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mascot_image_description][:description] %> + <%= f.text_field :mascot_image_description, + class: "form-control", + value: SiteConfig.mascot_image_description %> +
+ + <%= render "form_submission", f: f %> +
+
<% end %> @@ -889,26 +862,26 @@ target: "metaKeywordsBodyContainer", expanded: false } %> -
-
- <%= f.fields_for :meta_keywords do |meta_keywords_field| %> - <% SiteConfig.meta_keywords.each do |area, keywords| %> -
- <%= admin_config_label area.to_s %> -

- <%= area.capitalize %><%= "page" unless area == "default" %> keywords -

- <%= meta_keywords_field.text_field area, - class: "crayons-textfield", - value: SiteConfig.meta_keywords[area], - placeholder: Constants::SiteConfig::DETAILS[:meta_keywords][:placeholder] %> -
- <% end %> - <% end %> +
+
+ <%= f.fields_for :meta_keywords do |meta_keywords_field| %> + <% SiteConfig.meta_keywords.each do |area, keywords| %> +
+ <%= admin_config_label area.to_s %> +

+ <%= area.capitalize %><%= "page" unless area == "default" %> keywords +

+ <%= meta_keywords_field.text_field area, + class: "crayons-textfield", + value: SiteConfig.meta_keywords[area], + placeholder: Constants::SiteConfig::DETAILS[:meta_keywords][:placeholder] %> +
+ <% end %> + <% end %> - <%= render "form_submission", f: f %> -
-
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -921,47 +894,47 @@ target: "monetizationBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :shop_url, "Shop URL" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:shop_url][:description] %> - <%= f.text_field :shop_url, - class: "crayons-textfield", - value: SiteConfig.shop_url, - placeholder: Constants::SiteConfig::DETAILS[:shop_url][:placeholder] %> -
- -
- <%= admin_config_label :stripe_api_key, "Stripe API key" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:stripe_api_key][:description] %> - <%= f.text_field :stripe_api_key, - class: "crayons-textfield", - value: SiteConfig.stripe_api_key, - placeholder: Constants::SiteConfig::DETAILS[:stripe_api_key][:placeholder] %> -
- -
- <%= admin_config_label :stripe_publishable_key %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:stripe_publishable_key][:description] %> - <%= f.text_field :stripe_publishable_key, - class: "crayons-textfield", - value: SiteConfig.stripe_publishable_key, - placeholder: Constants::SiteConfig::DETAILS[:stripe_publishable_key][:placeholder] %> -
- -
- <%= admin_config_label :payment_pointer %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:payment_pointer][:description] %> - <%= f.text_field :payment_pointer, - class: "crayons-textfield", - value: SiteConfig.payment_pointer, - placeholder: Constants::SiteConfig::DETAILS[:payment_pointer][:placeholder] %> -
- - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :shop_url, "Shop URL" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:shop_url][:description] %> + <%= f.text_field :shop_url, + class: "crayons-textfield", + value: SiteConfig.shop_url, + placeholder: Constants::SiteConfig::DETAILS[:shop_url][:placeholder] %>
+ +
+ <%= admin_config_label :stripe_api_key, "Stripe API key" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:stripe_api_key][:description] %> + <%= f.text_field :stripe_api_key, + class: "crayons-textfield", + value: SiteConfig.stripe_api_key, + placeholder: Constants::SiteConfig::DETAILS[:stripe_api_key][:placeholder] %> +
+ +
+ <%= admin_config_label :stripe_publishable_key %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:stripe_publishable_key][:description] %> + <%= f.text_field :stripe_publishable_key, + class: "crayons-textfield", + value: SiteConfig.stripe_publishable_key, + placeholder: Constants::SiteConfig::DETAILS[:stripe_publishable_key][:placeholder] %> +
+ +
+ <%= admin_config_label :payment_pointer %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:payment_pointer][:description] %> + <%= f.text_field :payment_pointer, + class: "crayons-textfield", + value: SiteConfig.payment_pointer, + placeholder: Constants::SiteConfig::DETAILS[:payment_pointer][:placeholder] %> +
+ + <%= render "form_submission", f: f %> +
+
<% end %> @@ -974,51 +947,51 @@ target: "newsletterBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :mailchimp_api_key, "Mailchimp API Key" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_api_key][:description] %> - <%= f.text_field :mailchimp_api_key, - class: "crayons-textfield", - value: SiteConfig.mailchimp_api_key %> -
- -
- <%= admin_config_label :mailchimp_newsletter_id, "Main Newsletter" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_newsletter_id][:description] %> - <%= f.text_field :mailchimp_newsletter_id, - class: "crayons-textfield", - value: SiteConfig.mailchimp_newsletter_id %> -
- -
- <%= admin_config_label :mailchimp_sustaining_members_id, "Sustaining Members Newsletter" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_sustaining_members_id][:description] %> - <%= f.text_field :mailchimp_sustaining_members_id, - class: "crayons-textfield", - value: SiteConfig.mailchimp_sustaining_members_id %> -
- -
- <%= admin_config_label :mailchimp_tag_moderators_id, "Tag Moderators Newsletter" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_tag_moderators_id][:description] %> - <%= f.text_field :mailchimp_tag_moderators_id, - class: "crayons-textfield", - value: SiteConfig.mailchimp_tag_moderators_id %> -
- -
- <%= admin_config_label :mailchimp_community_moderators_id, "Community Moderators Newsletter" %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_community_moderators_id][:description] %> - <%= f.text_field :mailchimp_community_moderators_id, - class: "crayons-textfield", - value: SiteConfig.mailchimp_community_moderators_id %> -
- - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :mailchimp_api_key, "Mailchimp API Key" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_api_key][:description] %> + <%= f.text_field :mailchimp_api_key, + class: "crayons-textfield", + value: SiteConfig.mailchimp_api_key %>
+ +
+ <%= admin_config_label :mailchimp_newsletter_id, "Main Newsletter" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_newsletter_id][:description] %> + <%= f.text_field :mailchimp_newsletter_id, + class: "crayons-textfield", + value: SiteConfig.mailchimp_newsletter_id %> +
+ +
+ <%= admin_config_label :mailchimp_sustaining_members_id, "Sustaining Members Newsletter" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_sustaining_members_id][:description] %> + <%= f.text_field :mailchimp_sustaining_members_id, + class: "crayons-textfield", + value: SiteConfig.mailchimp_sustaining_members_id %> +
+ +
+ <%= admin_config_label :mailchimp_tag_moderators_id, "Tag Moderators Newsletter" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_tag_moderators_id][:description] %> + <%= f.text_field :mailchimp_tag_moderators_id, + class: "crayons-textfield", + value: SiteConfig.mailchimp_tag_moderators_id %> +
+ +
+ <%= admin_config_label :mailchimp_community_moderators_id, "Community Moderators Newsletter" %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:mailchimp_community_moderators_id][:description] %> + <%= f.text_field :mailchimp_community_moderators_id, + class: "crayons-textfield", + value: SiteConfig.mailchimp_community_moderators_id %> +
+ + <%= render "form_submission", f: f %> +
+
<% end %> @@ -1031,44 +1004,44 @@ target: "onboardingBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :onboarding_background_image %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:onboarding_background_image][:description] %> - <%= f.text_field :onboarding_background_image, - class: "crayons-textfield", - value: SiteConfig.onboarding_background_image, - placeholder: Constants::SiteConfig::DETAILS[:onboarding_background_image][:placeholder] %> -
-
- onboarding background image -
+
+
+
+ <%= admin_config_label :onboarding_background_image %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:onboarding_background_image][:description] %> + <%= f.text_field :onboarding_background_image, + class: "crayons-textfield", + value: SiteConfig.onboarding_background_image, + placeholder: Constants::SiteConfig::DETAILS[:onboarding_background_image][:placeholder] %> +
+
+ onboarding background image
+
-
- <%= admin_config_label :suggested_users %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:suggested_users][:description] %> - <%= f.text_field :suggested_users, - class: "crayons-textfield", - value: SiteConfig.suggested_users.join(","), - placeholder: Constants::SiteConfig::DETAILS[:suggested_users][:placeholder] %> -
- -
- <%= f.check_box :prefer_manual_suggested_users, checked: SiteConfig.prefer_manual_suggested_users, class: "crayons-checkbox" %> -
- <%= admin_config_label :prefer_manual_suggested_users %> -

- <%= Constants::SiteConfig::DETAILS[:prefer_manual_suggested_users][:description] %> -

-
-
- - <%= render "form_submission", f: f %> -
+
+ <%= admin_config_label :suggested_users %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:suggested_users][:description] %> + <%= f.text_field :suggested_users, + class: "crayons-textfield", + value: SiteConfig.suggested_users.join(","), + placeholder: Constants::SiteConfig::DETAILS[:suggested_users][:placeholder] %>
+ +
+ <%= f.check_box :prefer_manual_suggested_users, checked: SiteConfig.prefer_manual_suggested_users, class: "crayons-checkbox" %> +
+ <%= admin_config_label :prefer_manual_suggested_users %> +

+ <%= Constants::SiteConfig::DETAILS[:prefer_manual_suggested_users][:description] %> +

+
+
+ + <%= render "form_submission", f: f %> +
+
<% end %> @@ -1081,42 +1054,42 @@ target: "rateLimitsBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :user_considered_new_days %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:user_considered_new_days][:description] %> - <%= f.number_field :user_considered_new_days, - class: "crayons-textfield", - value: SiteConfig.user_considered_new_days, - placeholder: Constants::SiteConfig::DETAILS[:user_considered_new_days][:placeholder] %> -
- - <% configurable_rate_limits.each do |key, field_hash| %> -
- <%= admin_config_label field_hash[:title] %> -

- <%= field_hash[:description] %> -

- <%= f.number_field key, - class: "crayons-textfield", - value: SiteConfig.public_send(key), - min: field_hash[:min], - placeholder: field_hash[:placeholder] %> -
- <% end %> - -
- <%= admin_config_label :spam_trigger_terms %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:spam_trigger_terms][:description] %> - <%= f.text_area :spam_trigger_terms, - class: "crayons-textfield", - value: SiteConfig.spam_trigger_terms.join(","), - placeholder: Constants::SiteConfig::DETAILS[:spam_trigger_terms][:placeholder] %> -
- <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :user_considered_new_days %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:user_considered_new_days][:description] %> + <%= f.number_field :user_considered_new_days, + class: "crayons-textfield", + value: SiteConfig.user_considered_new_days, + placeholder: Constants::SiteConfig::DETAILS[:user_considered_new_days][:placeholder] %>
+ + <% configurable_rate_limits.each do |key, field_hash| %> +
+ <%= admin_config_label field_hash[:title] %> +

+ <%= field_hash[:description] %> +

+ <%= f.number_field key, + class: "crayons-textfield", + value: SiteConfig.public_send(key), + min: field_hash[:min], + placeholder: field_hash[:placeholder] %> +
+ <% end %> + +
+ <%= admin_config_label :spam_trigger_terms %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:spam_trigger_terms][:description] %> + <%= f.text_area :spam_trigger_terms, + class: "crayons-textfield", + value: SiteConfig.spam_trigger_terms.join(","), + placeholder: Constants::SiteConfig::DETAILS[:spam_trigger_terms][:placeholder] %> +
+ <%= render "form_submission", f: f %> +
+
<% end %> @@ -1129,34 +1102,34 @@ target: "socialMediaBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :twitter_hashtag %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:twitter_hashtag][:description] %> - <%= f.text_field :twitter_hashtag, - class: "crayons-textfield", - value: SiteConfig.twitter_hashtag.to_s, - placeholder: Constants::SiteConfig::DETAILS[:twitter_hashtag][:placeholder] %> -
- <%= f.fields_for :social_media_handles do |social_media_field| %> - <% SiteConfig.social_media_handles.each do |platform, username| %> -
- <%= admin_config_label platform %> -

- <%= platform.capitalize %> username -

- <%= social_media_field.text_field platform, - class: "crayons-textfield", - value: SiteConfig.social_media_handles[platform], - placeholder: "" %> -
- <% end %> - <% end %> - - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :twitter_hashtag %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:twitter_hashtag][:description] %> + <%= f.text_field :twitter_hashtag, + class: "crayons-textfield", + value: SiteConfig.twitter_hashtag.to_s, + placeholder: Constants::SiteConfig::DETAILS[:twitter_hashtag][:placeholder] %>
+ <%= f.fields_for :social_media_handles do |social_media_field| %> + <% SiteConfig.social_media_handles.each do |platform, username| %> +
+ <%= admin_config_label platform %> +

+ <%= platform.capitalize %> username +

+ <%= social_media_field.text_field platform, + class: "crayons-textfield", + value: SiteConfig.social_media_handles[platform], + placeholder: "" %> +
+ <% end %> + <% end %> + + <%= render "form_submission", f: f %> +
+
<% end %> @@ -1169,20 +1142,20 @@ target: "sponsorsContainer", expanded: false } %> -
-
-
- <%= admin_config_label :sponsor_headline %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:sponsor_headline][:description] %> - <%= f.text_field :sponsor_headline, - class: "crayons-textfield", - value: SiteConfig.sponsor_headline, - placeholder: Constants::SiteConfig::DETAILS[:sponsor_headline][:placeholder] %> -
- - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :sponsor_headline %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:sponsor_headline][:description] %> + <%= f.text_field :sponsor_headline, + class: "crayons-textfield", + value: SiteConfig.sponsor_headline, + placeholder: Constants::SiteConfig::DETAILS[:sponsor_headline][:placeholder] %>
+ + <%= render "form_submission", f: f %> +
+
<% end %> @@ -1195,21 +1168,21 @@ target: "tagsBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :sidebar_tags %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:sidebar_tags][:description] %> - <%= f.text_field :sidebar_tags, - class: "crayons-textfield", - value: SiteConfig.sidebar_tags.join(","), - placeholder: Constants::SiteConfig::DETAILS[:sidebar_tags][:placeholder], - pattern: "[a-z0-9,]+" %> -
- - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :sidebar_tags %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:sidebar_tags][:description] %> + <%= f.text_field :sidebar_tags, + class: "crayons-textfield", + value: SiteConfig.sidebar_tags.join(","), + placeholder: Constants::SiteConfig::DETAILS[:sidebar_tags][:placeholder], + pattern: "[a-z0-9,]+" %>
+ + <%= render "form_submission", f: f %> +
+
<% end %> @@ -1222,73 +1195,73 @@ target: "uxBodyContainer", expanded: false } %> -
-
-
- <%= admin_config_label :feed_style %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:feed_style][:description] %> - <%= f.text_field :feed_style, - class: "crayons-textfield", - value: SiteConfig.feed_style, - placeholder: Constants::SiteConfig::DETAILS[:feed_style][:placeholder] %> -
-
- <%= admin_config_label :feed_strategy %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:feed_strategy][:description] %> - <%= f.text_field :feed_strategy, - class: "crayons-textfield", - value: SiteConfig.feed_strategy, - placeholder: Constants::SiteConfig::DETAILS[:feed_strategy][:placeholder] %> -
-
- <%= admin_config_label :tag_feed_minimum_score %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:tag_feed_minimum_score][:description] %> - <%= f.number_field :tag_feed_minimum_score, - class: "crayons-textfield", - value: SiteConfig.tag_feed_minimum_score, - placeholder: Constants::SiteConfig::DETAILS[:tag_feed_minimum_score][:placeholder] %> -
-
- <%= admin_config_label :home_feed_minimum_score %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:home_feed_minimum_score][:description] %> - <%= f.number_field :home_feed_minimum_score, - class: "crayons-textfield", - value: SiteConfig.home_feed_minimum_score, - placeholder: Constants::SiteConfig::DETAILS[:home_feed_minimum_score][:placeholder] %> -
-
- <%= admin_config_label :default_font %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:default_font][:description] %> - <%= select_tag "site_config[default_font]", - options_for_select( - [%w[sans-serif sans_serif], %w[serif serif], %w[open-dyslexic open_dyslexic]], - SiteConfig.default_font, - ), - multiple: false, - class: "selectpicker" %> -
-
- <%= admin_config_label :primary_brand_color_hex %> - <%= admin_config_description Constants::SiteConfig::DETAILS[:primary_brand_color_hex][:description] %> - <%= f.color_field :primary_brand_color_hex, - class: "crayons-color-selector", - value: SiteConfig.primary_brand_color_hex, - pattern: "^#+([a-fA-F0-9]{6})$", - placeholder: Constants::SiteConfig::DETAILS[:primary_brand_color_hex][:placeholder] %> -
-
- <%= f.check_box :public, checked: SiteConfig.public, class: "crayons-checkbox" %> -
- <%= admin_config_label :public %> -

- Are most of the site pages (e.g. posts, profiles) public? Please take precaution when changing this setting. -

-
-
- - <%= render "form_submission", f: f %> -
+
+
+
+ <%= admin_config_label :feed_style %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:feed_style][:description] %> + <%= f.text_field :feed_style, + class: "crayons-textfield", + value: SiteConfig.feed_style, + placeholder: Constants::SiteConfig::DETAILS[:feed_style][:placeholder] %>
+
+ <%= admin_config_label :feed_strategy %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:feed_strategy][:description] %> + <%= f.text_field :feed_strategy, + class: "crayons-textfield", + value: SiteConfig.feed_strategy, + placeholder: Constants::SiteConfig::DETAILS[:feed_strategy][:placeholder] %> +
+
+ <%= admin_config_label :tag_feed_minimum_score %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:tag_feed_minimum_score][:description] %> + <%= f.number_field :tag_feed_minimum_score, + class: "crayons-textfield", + value: SiteConfig.tag_feed_minimum_score, + placeholder: Constants::SiteConfig::DETAILS[:tag_feed_minimum_score][:placeholder] %> +
+
+ <%= admin_config_label :home_feed_minimum_score %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:home_feed_minimum_score][:description] %> + <%= f.number_field :home_feed_minimum_score, + class: "crayons-textfield", + value: SiteConfig.home_feed_minimum_score, + placeholder: Constants::SiteConfig::DETAILS[:home_feed_minimum_score][:placeholder] %> +
+
+ <%= admin_config_label :default_font %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:default_font][:description] %> + <%= select_tag "site_config[default_font]", + options_for_select( + [%w[sans-serif sans_serif], %w[serif serif], %w[open-dyslexic open_dyslexic]], + SiteConfig.default_font, + ), + multiple: false, + class: "selectpicker" %> +
+
+ <%= admin_config_label :primary_brand_color_hex %> + <%= admin_config_description Constants::SiteConfig::DETAILS[:primary_brand_color_hex][:description] %> + <%= f.color_field :primary_brand_color_hex, + class: "crayons-color-selector", + value: SiteConfig.primary_brand_color_hex, + pattern: "^#+([a-fA-F0-9]{6})$", + placeholder: Constants::SiteConfig::DETAILS[:primary_brand_color_hex][:placeholder] %> +
+
+ <%= f.check_box :public, checked: SiteConfig.public, class: "crayons-checkbox" %> +
+ <%= admin_config_label :public %> +

+ Are most of the site pages (e.g. posts, profiles) public? Please take precaution when changing this setting. +

+
+
+ + <%= render "form_submission", f: f %> +
+
<% end %> diff --git a/app/views/devise/registrations/_registration_form.html.erb b/app/views/devise/registrations/_registration_form.html.erb index 67cc9f4e1..3ffd2dcb0 100644 --- a/app/views/devise/registrations/_registration_form.html.erb +++ b/app/views/devise/registrations/_registration_form.html.erb @@ -24,7 +24,7 @@ <% else %>
- <% if SiteConfig.allow_email_password_login %> + <% if Settings::Authentication.allow_email_password_login %>
Have a password? Continue with your email address diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index bce8a7895..ceef512ac 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,6 +1,6 @@ <% title "Welcome!" %> -<% if params[:state] == "email_signup" && SiteConfig.allow_email_password_registration %> +<% if params[:state] == "email_signup" && Settings::Authentication.allow_email_password_registration %> <%= render "shared/authentication/email_registration_form" %> <% elsif params[:state] == "email_signup" %>
diff --git a/app/views/feedback_messages/_form.html.erb b/app/views/feedback_messages/_form.html.erb index dd530071a..b8ef71df9 100644 --- a/app/views/feedback_messages/_form.html.erb +++ b/app/views/feedback_messages/_form.html.erb @@ -69,7 +69,7 @@ <% if ReCaptcha::CheckEnabled.call(current_user) %>
- <%= recaptcha_tags site_key: SiteConfig.recaptcha_site_key %> + <%= recaptcha_tags site_key: Settings::Authentication.recaptcha_site_key %>
<% end %> diff --git a/app/views/shared/authentication/_email_registration_form.html.erb b/app/views/shared/authentication/_email_registration_form.html.erb index 09e11974c..a075e6b30 100644 --- a/app/views/shared/authentication/_email_registration_form.html.erb +++ b/app/views/shared/authentication/_email_registration_form.html.erb @@ -29,15 +29,15 @@ <% else %>

Create your account

<% end %> - <% if SiteConfig.display_email_domain_allow_list_publicly && - SiteConfig.allowed_registration_email_domains.any? %> + <% if Settings::Authentication.display_email_domain_allow_list_publicly && + Settings::Authentication.allowed_registration_email_domains.any? %>
- <% if SiteConfig.allowed_registration_email_domains.one? %> - Registration restricted to @<%= SiteConfig.allowed_registration_email_domains.first %> emails. + <% if Settings::Authentication.allowed_registration_email_domains.one? %> + Registration restricted to @<%= Settings::Authentication.allowed_registration_email_domains.first %> emails. <% else %> Registration restricted to the following emails
    - <% SiteConfig.allowed_registration_email_domains.each do |domain| %> + <% Settings::Authentication.allowed_registration_email_domains.each do |domain| %>
  • @<%= domain %>
  • @@ -89,7 +89,7 @@ <% if ReCaptcha::CheckRegistrationEnabled.call %>
    - <%= recaptcha_tags site_key: SiteConfig.recaptcha_site_key %> + <%= recaptcha_tags site_key: Settings::Authentication.recaptcha_site_key %>
    <% end %> diff --git a/app/views/shared/authentication/_providers_registration_form.html.erb b/app/views/shared/authentication/_providers_registration_form.html.erb index 999b44d13..006604266 100644 --- a/app/views/shared/authentication/_providers_registration_form.html.erb +++ b/app/views/shared/authentication/_providers_registration_form.html.erb @@ -8,7 +8,7 @@ <% end %> <% end %> <% end %> - <% if params[:state] == "new-user" && SiteConfig.allow_email_password_registration && !SiteConfig.invite_only_mode %> + <% if params[:state] == "new-user" && Settings::Authentication.allow_email_password_registration && !Settings::Authentication.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", diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index b17b928f3..804b07952 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,27 +1,27 @@ TWITTER_OMNIAUTH_SETUP = lambda do |env| - env["omniauth.strategy"].options[:consumer_key] = SiteConfig.twitter_key - env["omniauth.strategy"].options[:consumer_secret] = SiteConfig.twitter_secret + env["omniauth.strategy"].options[:consumer_key] = Settings::Authentication.twitter_key + env["omniauth.strategy"].options[:consumer_secret] = Settings::Authentication.twitter_secret end GITHUB_OMNIUATH_SETUP = lambda do |env| - env["omniauth.strategy"].options[:client_id] = SiteConfig.github_key - env["omniauth.strategy"].options[:client_secret] = SiteConfig.github_secret + env["omniauth.strategy"].options[:client_id] = Settings::Authentication.github_key + env["omniauth.strategy"].options[:client_secret] = Settings::Authentication.github_secret env["omniauth.strategy"].options[:scope] = "user:email" end FACEBOOK_OMNIAUTH_SETUP = lambda do |env| - env["omniauth.strategy"].options[:client_id] = SiteConfig.facebook_key - env["omniauth.strategy"].options[:client_secret] = SiteConfig.facebook_secret + env["omniauth.strategy"].options[:client_id] = Settings::Authentication.facebook_key + env["omniauth.strategy"].options[:client_secret] = Settings::Authentication.facebook_secret env["omniauth.strategy"].options[:token_params][:parse] = :json end APPLE_OMNIAUTH_SETUP = lambda do |env| - env["omniauth.strategy"].options[:client_id] = SiteConfig.apple_client_id + env["omniauth.strategy"].options[:client_id] = Settings::Authentication.apple_client_id env["omniauth.strategy"].options[:scope] = "email name" - env["omniauth.strategy"].options[:key_id] = SiteConfig.apple_key_id - env["omniauth.strategy"].options[:pem] = SiteConfig.apple_pem.to_s.gsub("\\n", "\n") + env["omniauth.strategy"].options[:key_id] = Settings::Authentication.apple_key_id + env["omniauth.strategy"].options[:pem] = Settings::Authentication.apple_pem.to_s.gsub("\\n", "\n") env["omniauth.strategy"].options[:provider_ignores_state] = true - env["omniauth.strategy"].options[:team_id] = SiteConfig.apple_team_id + env["omniauth.strategy"].options[:team_id] = Settings::Authentication.apple_team_id end Devise.setup do |config| diff --git a/config/initializers/rails_settings.rb b/config/initializers/rails_settings.rb new file mode 100644 index 000000000..d1c58fa1e --- /dev/null +++ b/config/initializers/rails_settings.rb @@ -0,0 +1,44 @@ +require "request_store" + +# Completely remove original implementation +RailsSettings.__send__(:remove_const, :RequestCache) + +module RailsSettings + class Base < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord + def self.inherited(subclass) + super + + # Define a unique RequestCache class for each settings klass + request_cache = Class.new(ActiveSupport::CurrentAttributes) do + attribute :settings + end + subclass.const_set(:RequestCache, request_cache) + + # Override existing methods to use the local RequestCache class + subclass.instance_eval do + define_singleton_method(:cache_key) do + subclass_cache_key = subclass.name.underscore.tr("/", "_") + scope = [subclass_cache_key] + scope << @cache_prefix.call if @cache_prefix + scope.join("/") + end + + define_singleton_method(:clear_cache) do + subclass::RequestCache.reset + Rails.cache.delete(cache_key) + end + + define_singleton_method(:_all_settings) do + subclass::RequestCache.settings ||= + Rails.cache.fetch(cache_key, expires_in: 1.week) do + vars = unscoped.select("var, value") + result = {} + vars.each { |record| result[record.var] = record.value } + result.with_indifferent_access + end + end + singleton_class.instance_eval { private :_all_settings } + end + end + end +end diff --git a/config/routes.rb b/config/routes.rb index a03a022b6..452dd973d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,9 @@ Rails.application.routes.draw do resources :organization_memberships, only: %i[update destroy create] resources :permissions, only: %i[index] resources :reactions, only: [:update] + namespace :settings do + resources :authentications, only: [:create] + end namespace :users do resources :gdpr_delete_requests, only: %i[index destroy] end diff --git a/cypress/integration/adminFlows/config/authenticationSection.spec.js b/cypress/integration/adminFlows/config/authenticationSection.spec.js index 586564798..a2f176c0f 100644 --- a/cypress/integration/adminFlows/config/authenticationSection.spec.js +++ b/cypress/integration/adminFlows/config/authenticationSection.spec.js @@ -91,7 +91,6 @@ describe('Authentication Section', () => { .findByText('Update Site Configuration') .click(); - cy.findByText('Setup not complete').should('be.visible'); cy.get('.crayons-modal__box__body > ul > li') .contains('facebook') .should('be.visible'); @@ -107,8 +106,8 @@ describe('Authentication Section', () => { cy.get('@authSectionForm').findByText('Authentication').click(); cy.get('#facebook-auth-btn').click(); - cy.get('#site_config_facebook_key').type('randomkey'); - cy.get('#site_config_facebook_secret').type('randomsecret'); + cy.get('#settings_authentication_facebook_key').type('randomkey'); + cy.get('#settings_authentication_facebook_secret').type('randomsecret'); cy.get('@user').then(({ username }) => { cy.get('@authSectionForm') .findByPlaceholderText('Confirmation text') diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 18333a8b7..5fad29593 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -127,16 +127,16 @@ Cypress.Commands.add( ) => { return cy.request( 'POST', - '/admin/config', - `utf8=%E2%9C%93&site_config%5Binvite_only_mode%5D=${toPayload( + '/admin/settings/authentications', + `utf8=%E2%9C%93&settings_authentication%5Binvite_only_mode%5D=${toPayload( inviteOnlyMode, - )}&site_config%5Ballow_email_password_registration%5D=${toPayload( + )}&settings_authentication%5Ballow_email_password_registration%5D=${toPayload( emailRegistration, - )}&site_config%5Ballowed_registration_email_domains%5D=${allowedEmailDomains}&site_config%5Bdisplay_email_domain_allow_list_publicly%5D=${toPayload( + )}&settings_authentication%5Ballowed_registration_email_domains%5D=${allowedEmailDomains}&settings_authentication%5Bdisplay_email_domain_allow_list_publicly%5D=${toPayload( publicEmailDomainList, - )}&site_config%5Brequire_captcha_for_email_password_registration%5D=${toPayload( + )}&settings_authentication%5Brequire_captcha_for_email_password_registration%5D=${toPayload( requireRecaptcha, - )}&site_config%5Brecaptcha_site_key%5D=${recaptchaSiteKey}&site_config%5Brecaptcha_secret_key%5D=${recaptchaSecretKey}&site_config%5Bauth_providers_to_enable%5D=${authProvidersToEnable}&site_config%5Bfacebook_key%5D=${facebookKey}&site_config%5Bfacebook_secret%5D=${facebookSecret}&site_config%5Bgithub_key%5D=${githubKey}&site_config%5Bgithub_secret%5D=${githubSecret}&site_config%5Btwitter_key%5D=${twitterKey}&site_config%5Btwitter_secret%5D=${twitterSecret}&confirmation=My+username+is+%40${username}+and+this+action+is+100%25+safe+and+appropriate.&commit=Update+Site+Configuration`, + )}&settings_authentication%5Brecaptcha_site_key%5D=${recaptchaSiteKey}&settings_authentication%5Brecaptcha_secret_key%5D=${recaptchaSecretKey}&settings_authentication%5Bauth_providers_to_enable%5D=${authProvidersToEnable}&settings_authentication%5Bfacebook_key%5D=${facebookKey}&settings_authentication%5Bfacebook_secret%5D=${facebookSecret}&settings_authentication%5Bgithub_key%5D=${githubKey}&settings_authentication%5Bgithub_secret%5D=${githubSecret}&settings_authentication%5Btwitter_key%5D=${twitterKey}&settings_authentication%5Btwitter_secret%5D=${twitterSecret}&confirmation=My+username+is+%40${username}+and+this+action+is+100%25+safe+and+appropriate.&commit=Update+Site+Configuration`, ); }, ); diff --git a/db/migrate/20210316091102_create_settings.rb b/db/migrate/20210316091102_create_settings.rb new file mode 100644 index 000000000..c25b39293 --- /dev/null +++ b/db/migrate/20210316091102_create_settings.rb @@ -0,0 +1,16 @@ +class CreateSettings < ActiveRecord::Migration[6.0] + def self.up + create_table :settings_authentications do |t| + t.string :var, null: false + t.text :value, null: true + + t.timestamps + end + + add_index :settings_authentications, :var, unique: true + end + + def self.down + drop_table :settings_authentications + end +end diff --git a/db/schema.rb b/db/schema.rb index 9df9cd708..d9734c957 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1048,6 +1048,14 @@ ActiveRecord::Schema.define(version: 2021_03_31_181505) do t.index ["name"], name: "index_roles_on_name" end + create_table "settings_authentications", force: :cascade do |t| + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.text "value" + t.string "var", null: false + t.index ["var"], name: "index_settings_authentications_on_var", unique: true + end + create_table "site_configs", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false diff --git a/db/seeds.rb b/db/seeds.rb index d7e6a8773..43c4a994a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -17,7 +17,7 @@ puts "Seeding with multiplication factor: #{SEEDS_MULTIPLIER}\n\n" SiteConfig.public = true SiteConfig.waiting_on_first_user = false -SiteConfig.authentication_providers = Authentication::Providers.available +Settings::Authentication.providers = Authentication::Providers.available ############################################################################## diff --git a/lib/data_update_scripts/20210316091354_move_authentication_settings.rb b/lib/data_update_scripts/20210316091354_move_authentication_settings.rb new file mode 100644 index 000000000..6f7b29bd8 --- /dev/null +++ b/lib/data_update_scripts/20210316091354_move_authentication_settings.rb @@ -0,0 +1,42 @@ +module DataUpdateScripts + class MoveAuthenticationSettings + AUTHENTICATION_SETTINGS = %w[ + allow_email_password_login + allow_email_password_registration + apple_client_id + apple_key_id + apple_pem + apple_team_id + display_email_domain_allow_list_publicly + facebook_key + facebook_secret + github_key + github_secret + invite_only_mode + require_captcha_for_email_password_registration + twitter_key + twitter_secret + ].freeze + + ATTRIBUTES = %i[var value created_at updated_at].freeze + + def run + return if Settings::Authentication.any? + + SiteConfig.transaction do + config_relation = SiteConfig.where(var: AUTHENTICATION_SETTINGS) + config_values = config_relation.pluck(*ATTRIBUTES).map do |values| + ATTRIBUTES.zip(values).to_h + end + Settings::Authentication.insert_all(config_values) if config_values.present? + + # This field has a validation we don't want to skip + Settings::Authentication.allowed_registration_email_domains = + SiteConfig.allowed_registration_email_domains + + # This field got renamed so we migrate it explicitly + Settings::Authentication.providers = SiteConfig.authentication_providers + end + end + end +end diff --git a/spec/helpers/authentication_helper_spec.rb b/spec/helpers/authentication_helper_spec.rb index 437df1e22..f2d883043 100644 --- a/spec/helpers/authentication_helper_spec.rb +++ b/spec/helpers/authentication_helper_spec.rb @@ -58,8 +58,8 @@ RSpec.describe AuthenticationHelper, type: :helper do describe "#authentication_provider_enabled?" do before do - allow(SiteConfig).to receive(:invite_only_mode).and_return(false) - allow(SiteConfig).to receive(:authentication_providers).and_return(%i[twitter github]) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(false) + allow(Settings::Authentication).to receive(:providers).and_return(%i[twitter github]) end it "returns true when a provider has been enabled" do @@ -76,9 +76,9 @@ RSpec.describe AuthenticationHelper, type: :helper do describe "tooltip classes, attributes and content" do context "when invite-only-mode enabled and no enabled registration options" do before do - allow(SiteConfig).to receive(:invite_only_mode).and_return(true) - allow(SiteConfig).to receive(:authentication_providers).and_return([]) - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(false) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(true) + allow(Settings::Authentication).to receive(:providers).and_return([]) + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(false) end it "returns 'crayons-tooltip' class for relevant helpers" do diff --git a/spec/models/settings/authentication_spec.rb b/spec/models/settings/authentication_spec.rb new file mode 100644 index 000000000..ca7b686f8 --- /dev/null +++ b/spec/models/settings/authentication_spec.rb @@ -0,0 +1,19 @@ +require "rails_helper" + +RSpec.describe Settings::Authentication, type: :model do + describe "validations" do + describe "validating domain lists" do + it "allows valid domain lists" do + expect do + described_class.allowed_registration_email_domains = "example.com, example2.com" + end.not_to raise_error + end + + it "rejects invalid domain lists" do + expect do + described_class.allowed_registration_email_domains = "example.com, e.c" + end.to raise_error(/must be a comma-separated list of valid domains/) + end + end + end +end diff --git a/spec/models/site_config_spec.rb b/spec/models/site_config_spec.rb index 4770facf4..fab0ee558 100644 --- a/spec/models/site_config_spec.rb +++ b/spec/models/site_config_spec.rb @@ -27,20 +27,6 @@ RSpec.describe SiteConfig, type: :model do end end - describe "validating domain lists" do - it "allows valid domain lists" do - expect do - described_class.allowed_registration_email_domains = "example.com, example2.com" - end.not_to raise_error - end - - it "rejects invalid domain lists" do - expect do - described_class.allowed_registration_email_domains = "example.com, e.c" - end.to raise_error(/must be a comma-separated list of valid domains/) - end - end - describe "validating emojis strings" do it "allows emoji-only strings" do expect do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9b44107e0..c9b2e2be9 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -30,7 +30,7 @@ RSpec.describe User, type: :model do before do omniauth_mock_providers_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end describe "validations" do @@ -884,7 +884,7 @@ RSpec.describe User, type: :model do end it "returns true if the user has all the enabled providers" do - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) user = create(:user, :with_identity) diff --git a/spec/policies/github_repo_policy_spec.rb b/spec/policies/github_repo_policy_spec.rb index ff3785c5e..35d3358f5 100644 --- a/spec/policies/github_repo_policy_spec.rb +++ b/spec/policies/github_repo_policy_spec.rb @@ -23,7 +23,7 @@ RSpec.describe GithubRepoPolicy, type: :policy do before do omniauth_mock_github_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end it { is_expected.to permit_actions(%i[index update_or_create]) } diff --git a/spec/requests/admin/configs_spec.rb b/spec/requests/admin/configs_spec.rb index 6cc29048a..93eae7947 100644 --- a/spec/requests/admin/configs_spec.rb +++ b/spec/requests/admin/configs_spec.rb @@ -48,13 +48,12 @@ RSpec.describe "/admin/config", type: :request do end it "updates site config admin action taken" do - Timecop.freeze do - expect(SiteConfig.admin_action_taken_at).not_to eq(5.minutes.ago) - allow(SiteConfig).to receive(:admin_action_taken_at).and_return(5.minutes.ago) - post "/admin/config", params: { site_config: { health_check_token: "token" }, - confirmation: confirmation_message } - expect(SiteConfig.admin_action_taken_at).to eq(5.minutes.ago) - end + expect do + post "/admin/config", params: { + site_config: { health_check_token: "token" }, + confirmation: confirmation_message + } + end.to change(SiteConfig, :admin_action_taken_at) end describe "API tokens" do @@ -75,15 +74,15 @@ RSpec.describe "/admin/config", type: :request do describe "Authentication" do it "updates enabled authentication providers" do enabled = Authentication::Providers.available.last.to_s - post admin_config_path, params: { - site_config: { + post admin_settings_authentications_path, params: { + settings_authentication: { "#{enabled}_key": "someKey", "#{enabled}_secret": "someSecret", auth_providers_to_enable: enabled }, confirmation: confirmation_message } - expect(SiteConfig.authentication_providers).to eq([enabled]) + expect(Settings::Authentication.providers).to eq([enabled]) end describe "Campaigns" do @@ -97,81 +96,97 @@ RSpec.describe "/admin/config", type: :request do it "strips empty elements" do provider = Authentication::Providers.available.last.to_s enabled = "#{provider}, '', nil" - post admin_config_path, params: { - site_config: { + post admin_settings_authentications_path, params: { + settings_authentication: { "#{provider}_key": "someKey", "#{provider}_secret": "someSecret", auth_providers_to_enable: enabled }, confirmation: confirmation_message } - expect(SiteConfig.authentication_providers).to eq([provider]) + expect(Settings::Authentication.providers).to eq([provider]) end it "does not update enabled authentication providers if any associated key missing" do enabled = Authentication::Providers.available.first.to_s - post admin_config_path, params: { - site_config: { + post admin_settings_authentications_path, params: { + settings_authentication: { "#{enabled}_key": "someKey", "#{enabled}_secret": "", auth_providers_to_enable: enabled }, confirmation: confirmation_message } - expect(SiteConfig.authentication_providers).to eq([]) + expect(Settings::Authentication.providers).to eq([]) end it "enables proper domains to allow list" do proper_list = "dev.to, forem.com, forem.dev" - post "/admin/config", params: { site_config: { allowed_registration_email_domains: proper_list }, - confirmation: confirmation_message } - expect(SiteConfig.allowed_registration_email_domains).to eq(%w[dev.to forem.com forem.dev]) + post admin_settings_authentications_path, params: { + settings_authentication: { allowed_registration_email_domains: proper_list }, + confirmation: confirmation_message + } + expect(Settings::Authentication.allowed_registration_email_domains).to eq(%w[dev.to forem.com forem.dev]) end it "allows 2-character domains" do proper_list = "dev.to, forem.com, 2u.com" - post "/admin/config", params: { site_config: { allowed_registration_email_domains: proper_list }, - confirmation: confirmation_message } - expect(SiteConfig.allowed_registration_email_domains).to eq(%w[dev.to forem.com 2u.com]) + post admin_settings_authentications_path, params: { + settings_authentication: { allowed_registration_email_domains: proper_list }, + confirmation: confirmation_message + } + expect(Settings::Authentication.allowed_registration_email_domains).to eq(%w[dev.to forem.com 2u.com]) end it "does not allow improper domain list" do impproper_list = "dev.to, foremcom, forem.dev" - post "/admin/config", params: { site_config: { allowed_registration_email_domains: impproper_list }, - confirmation: confirmation_message } - expect(SiteConfig.allowed_registration_email_domains).not_to eq(%w[dev.to foremcom forem.dev]) + post admin_settings_authentications_path, params: { + settings_authentication: { allowed_registration_email_domains: impproper_list }, + confirmation: confirmation_message + } + expect(Settings::Authentication.allowed_registration_email_domains).not_to eq(%w[dev.to foremcom forem.dev]) end it "enables display_email_domain_allow_list_publicly" do - post "/admin/config", params: { site_config: { display_email_domain_allow_list_publicly: true }, - confirmation: confirmation_message } - expect(SiteConfig.display_email_domain_allow_list_publicly).to be(true) + post admin_settings_authentications_path, params: { + settings_authentication: { display_email_domain_allow_list_publicly: true }, + confirmation: confirmation_message + } + expect(Settings::Authentication.display_email_domain_allow_list_publicly).to be(true) end it "enables email authentication" do - post "/admin/config", params: { site_config: { allow_email_password_registration: true }, - confirmation: confirmation_message } - expect(SiteConfig.allow_email_password_registration).to be(true) - expect(SiteConfig.allow_email_password_login).to be(true) + post admin_settings_authentications_path, params: { + settings_authentication: { allow_email_password_registration: true }, + confirmation: confirmation_message + } + expect(Settings::Authentication.allow_email_password_registration).to be(true) + expect(Settings::Authentication.allow_email_password_login).to be(true) end it "disables email authentication" do - post "/admin/config", params: { site_config: { allow_email_password_registration: false }, - confirmation: confirmation_message } - expect(SiteConfig.allow_email_password_registration).to be(false) - expect(SiteConfig.allow_email_password_login).to be(true) + post admin_settings_authentications_path, params: { + settings_authentication: { allow_email_password_registration: false }, + confirmation: confirmation_message + } + expect(Settings::Authentication.allow_email_password_registration).to be(false) + expect(Settings::Authentication.allow_email_password_login).to be(true) end it "enables invite-only-mode" do - post "/admin/config", params: { site_config: { invite_only_mode: true }, - confirmation: confirmation_message } - expect(SiteConfig.invite_only_mode).to be(true) + post admin_settings_authentications_path, params: { + settings_authentication: { invite_only_mode: true }, + confirmation: confirmation_message + } + expect(Settings::Authentication.invite_only_mode).to be(true) end it "disables invite-only-mode & enables just email registration" do - post "/admin/config", params: { site_config: { invite_only_mode: false }, - confirmation: confirmation_message } - expect(SiteConfig.invite_only_mode).to be(false) + post admin_settings_authentications_path, params: { + settings_authentication: { invite_only_mode: false }, + confirmation: confirmation_message + } + expect(Settings::Authentication.invite_only_mode).to be(false) end end @@ -449,7 +464,7 @@ RSpec.describe "/admin/config", type: :request do expect(SiteConfig.mascot_footer_image_width).to eq(expected_default_mascot_footer_image_width) post "/admin/config", params: { site_config: - { mascot_footer_image_width: expected_mascot_footer_image_width }, + { mascot_footer_image_width: expected_mascot_footer_image_width }, confirmation: confirmation_message } expect(SiteConfig.mascot_footer_image_width).to eq(expected_mascot_footer_image_width) end @@ -461,7 +476,7 @@ RSpec.describe "/admin/config", type: :request do expect(SiteConfig.mascot_footer_image_height).to eq(expected_default_mascot_footer_image_height) post "/admin/config", params: { site_config: - { mascot_footer_image_height: expected_mascot_footer_image_height }, + { mascot_footer_image_height: expected_mascot_footer_image_height }, confirmation: confirmation_message } expect(SiteConfig.mascot_footer_image_height).to eq(expected_mascot_footer_image_height) end @@ -738,12 +753,12 @@ RSpec.describe "/admin/config", type: :request do it "updates recaptcha_site_key and recaptcha_secret_key" do site_key = "hi-ho" secret_key = "lets-go" - post "/admin/config", params: { - site_config: { recaptcha_site_key: site_key, recaptcha_secret_key: secret_key }, + post admin_settings_authentications_path, params: { + settings_authentication: { recaptcha_site_key: site_key, recaptcha_secret_key: secret_key }, confirmation: confirmation_message } - expect(SiteConfig.recaptcha_site_key).to eq site_key - expect(SiteConfig.recaptcha_secret_key).to eq secret_key + expect(Settings::Authentication.recaptcha_site_key).to eq site_key + expect(Settings::Authentication.recaptcha_secret_key).to eq secret_key end end diff --git a/spec/requests/admin/users_spec.rb b/spec/requests/admin/users_spec.rb index f15e1b614..825b54104 100644 --- a/spec/requests/admin/users_spec.rb +++ b/spec/requests/admin/users_spec.rb @@ -151,7 +151,7 @@ RSpec.describe "admin/users", type: :request do before do omniauth_mock_providers_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end it "removes the given identity" do diff --git a/spec/requests/api/v0/admin/configs_spec.rb b/spec/requests/api/v0/admin/configs_spec.rb index 2c922b381..337ba146d 100644 --- a/spec/requests/api/v0/admin/configs_spec.rb +++ b/spec/requests/api/v0/admin/configs_spec.rb @@ -64,9 +64,11 @@ RSpec.describe "Api::V0::Admin::Configs", type: :request do it "enables proper domains to allow list" do proper_list = "dev.to, forem.com, forem.dev" - put api_admin_config_path, params: { site_config: { allowed_registration_email_domains: proper_list } }.to_json, + put api_admin_config_path, params: { + site_config: { allowed_registration_email_domains: proper_list } + }.to_json, headers: headers - expect(SiteConfig.allowed_registration_email_domains).to eq(%w[dev.to forem.com forem.dev]) + expect(Settings::Authentication.allowed_registration_email_domains).to eq(%w[dev.to forem.com forem.dev]) end it "does not allow improper domain list" do @@ -74,7 +76,7 @@ RSpec.describe "Api::V0::Admin::Configs", type: :request do put api_admin_config_path, params: { site_config: { allowed_registration_email_domains: improper_list } }.to_json, headers: headers - expect(SiteConfig.allowed_registration_email_domains).not_to eq(%w[dev.to foremcom forem.dev]) + expect(Settings::Authentication.allowed_registration_email_domains).not_to eq(%w[dev.to foremcom forem.dev]) end it "removes space suggested_tags" do diff --git a/spec/requests/editor_spec.rb b/spec/requests/editor_spec.rb index be4d5cd9f..40b68f215 100644 --- a/spec/requests/editor_spec.rb +++ b/spec/requests/editor_spec.rb @@ -12,7 +12,7 @@ RSpec.describe "Editor", type: :request do context "when email login is allowed in /admin/config" do before do - allow(SiteConfig).to receive(:allow_email_password_login).and_return(true) + allow(Settings::Authentication).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 diff --git a/spec/requests/feedback_messages_spec.rb b/spec/requests/feedback_messages_spec.rb index 6aa59b441..12fa8504e 100644 --- a/spec/requests/feedback_messages_spec.rb +++ b/spec/requests/feedback_messages_spec.rb @@ -13,8 +13,8 @@ RSpec.describe "feedback_messages", type: :request do end def mock_recaptcha_config_enabled - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return("someSecretKey") - allow(SiteConfig).to receive(:recaptcha_site_key).and_return("someSiteKey") + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return("someSecretKey") + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return("someSiteKey") end valid_abuse_report_params = { @@ -81,8 +81,8 @@ RSpec.describe "feedback_messages", type: :request do context "with valid params and recaptcha not configured" do before do - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return(nil) - allow(SiteConfig).to receive(:recaptcha_site_key).and_return(nil) + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return(nil) + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return(nil) end it "does not show the recaptcha tag" do diff --git a/spec/requests/github_repos_spec.rb b/spec/requests/github_repos_spec.rb index 7246f5a34..10c952738 100644 --- a/spec/requests/github_repos_spec.rb +++ b/spec/requests/github_repos_spec.rb @@ -41,7 +41,7 @@ RSpec.describe "GithubRepos", type: :request do before do omniauth_mock_github_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) allow(Github::OauthClient).to receive(:new).and_return(github_client) end diff --git a/spec/requests/registrations_spec.rb b/spec/requests/registrations_spec.rb index 824ccc424..7d039ac70 100644 --- a/spec/requests/registrations_spec.rb +++ b/spec/requests/registrations_spec.rb @@ -18,7 +18,7 @@ RSpec.describe "Registrations", type: :request do it "only shows the single sign on options if they are present" do allow(Authentication::Providers).to receive(:enabled).and_return([]) - allow(SiteConfig).to receive(:allow_email_password_login).and_return(false) + allow(Settings::Authentication).to receive(:allow_email_password_login).and_return(false) get sign_up_path @@ -28,7 +28,7 @@ RSpec.describe "Registrations", type: :request do context "when email login is enabled in /admin/config" do before do - allow(SiteConfig).to receive(:allow_email_password_login).and_return(true) + allow(Settings::Authentication).to receive(:allow_email_password_login).and_return(true) end it "shows the sign in text for password based authentication" do @@ -40,7 +40,7 @@ RSpec.describe "Registrations", type: :request do context "when email login is disabled in /admin/config" do before do - allow(SiteConfig).to receive(:allow_email_password_login).and_return(false) + allow(Settings::Authentication).to receive(:allow_email_password_login).and_return(false) end it "does not show the sign in text for password based authentication" do @@ -62,7 +62,7 @@ RSpec.describe "Registrations", type: :request do describe "Create Account" do context "when email registration allowed" do - before { allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) } + before { allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(true) } it "shows the sign in page with email option" do get sign_up_path, params: { state: "new-user" } @@ -78,10 +78,10 @@ RSpec.describe "Registrations", type: :request do end context "when email registration not allowed" do - before { allow(SiteConfig).to receive(:allow_email_password_registration).and_return(false) } + before { allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(false) } it "does not show email sign up option" do - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(false) + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(false) get sign_up_path, params: { state: "new-user" } expect(response.body).not_to include("Sign up with Email") @@ -90,10 +90,10 @@ RSpec.describe "Registrations", type: :request do context "when email registration allowed and captcha required" do before do - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return("someSecretKey") - allow(SiteConfig).to receive(:recaptcha_site_key).and_return("someSiteKey") - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) - allow(SiteConfig).to receive(:require_captcha_for_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return("someSecretKey") + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return("someSiteKey") + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:require_captcha_for_email_password_registration).and_return(true) end it "displays the captcha box on email signup page" do @@ -162,7 +162,8 @@ RSpec.describe "Registrations", type: :request do context "when site is not configured to accept email registration" do before do - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(false) + allow(Settings::Authentication) + .to receive(:allow_email_password_registration).and_return(false) end it "disallows communities where email registration is not allowed" do @@ -172,7 +173,8 @@ RSpec.describe "Registrations", type: :request do context "when site is configured to accept email registration" do before do - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) + allow(Settings::Authentication) + .to receive(:allow_email_password_registration).and_return(true) end it "does not raise disallowed if community is set to allow email" do @@ -228,8 +230,8 @@ RSpec.describe "Registrations", type: :request do context "when email registration allowed and email allow list empty" do before do - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) - allow(SiteConfig).to receive(:allowed_registration_email_domains).and_return([]) + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:allowed_registration_email_domains).and_return([]) end it "creates user when email in allow list" do @@ -245,8 +247,9 @@ RSpec.describe "Registrations", type: :request do context "when email registration allowed and email allow list present" do before do - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) - allow(SiteConfig).to receive(:allowed_registration_email_domains).and_return(["dev.to", "forem.com"]) + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:allowed_registration_email_domains).and_return(["dev.to", + "forem.com"]) end it "does not create user when email not in allow list" do @@ -272,10 +275,10 @@ RSpec.describe "Registrations", type: :request do context "when site configured to accept email registration AND require captcha" do before do - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return("someSecretKey") - allow(SiteConfig).to receive(:recaptcha_site_key).and_return("someSiteKey") - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) - allow(SiteConfig).to receive(:require_captcha_for_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return("someSecretKey") + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return("someSiteKey") + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:require_captcha_for_email_password_registration).and_return(true) end it "creates user when valid params passed and recaptcha completed" do diff --git a/spec/requests/user/user_settings_spec.rb b/spec/requests/user/user_settings_spec.rb index 2a4d9c5a7..090186b2e 100644 --- a/spec/requests/user/user_settings_spec.rb +++ b/spec/requests/user/user_settings_spec.rb @@ -348,7 +348,7 @@ RSpec.describe "UserSettings", type: :request do before do omniauth_mock_providers_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) sign_in user end diff --git a/spec/services/authentication/authenticator_spec.rb b/spec/services/authentication/authenticator_spec.rb index ef547a008..9e596c7b2 100644 --- a/spec/services/authentication/authenticator_spec.rb +++ b/spec/services/authentication/authenticator_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe Authentication::Authenticator, type: :service do before do omniauth_mock_providers_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end context "when authenticating through an unknown provider" do diff --git a/spec/services/authentication/providers_spec.rb b/spec/services/authentication/providers_spec.rb index 88698e9e1..8d6268616 100644 --- a/spec/services/authentication/providers_spec.rb +++ b/spec/services/authentication/providers_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Authentication::Providers, type: :service do end it "raises an exception if a provider is available but not enabled" do - allow(SiteConfig).to receive(:authentication_providers).and_return(%w[github]) + allow(Settings::Authentication).to receive(:providers).and_return(%w[github]) expect do described_class.get!(:twitter) @@ -17,7 +17,7 @@ RSpec.describe Authentication::Providers, type: :service do end it "loads the correct provider class" do - allow(SiteConfig).to receive(:authentication_providers).and_return(described_class.available) + allow(Settings::Authentication).to receive(:providers).and_return(described_class.available) is_subclass_of = ( described_class.get!(:twitter) < Authentication::Providers::Provider @@ -36,7 +36,7 @@ RSpec.describe Authentication::Providers, type: :service do describe ".enabled" do context "when one of the available providers is disabled" do it "only lists those that remain enabled" do - allow(SiteConfig).to receive(:authentication_providers).and_return(%w[github]) + allow(Settings::Authentication).to receive(:providers).and_return(%w[github]) expect(described_class.enabled).to eq(%i[github]) end @@ -45,13 +45,13 @@ RSpec.describe Authentication::Providers, type: :service do describe ".enabled?" do it "returns true if a provider is enabled" do - allow(SiteConfig).to receive(:authentication_providers).and_return(%w[github]) + allow(Settings::Authentication).to receive(:providers).and_return(%w[github]) expect(described_class.enabled?(:github)).to be(true) end it "returns false if a provider is not enabled" do - allow(SiteConfig).to receive(:authentication_providers).and_return(%w[twitter]) + allow(Settings::Authentication).to receive(:providers).and_return(%w[twitter]) expect(described_class.enabled?(:github)).to be(false) end diff --git a/spec/services/broadcasts/welcome_notification/generator_spec.rb b/spec/services/broadcasts/welcome_notification/generator_spec.rb index e8272f6a0..1e89c0e46 100644 --- a/spec/services/broadcasts/welcome_notification/generator_spec.rb +++ b/spec/services/broadcasts/welcome_notification/generator_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Broadcasts::WelcomeNotification::Generator, type: :service do allow(Notification).to receive(:send_welcome_notification).and_call_original allow(User).to receive(:mascot_account).and_return(mascot_account) allow(SiteConfig).to receive(:staff_user_id).and_return(mascot_account.id) - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end it "requires a valid user id" do diff --git a/spec/services/re_captcha/check_enabled_spec.rb b/spec/services/re_captcha/check_enabled_spec.rb index 7936475dc..7362cba2b 100644 --- a/spec/services/re_captcha/check_enabled_spec.rb +++ b/spec/services/re_captcha/check_enabled_spec.rb @@ -14,8 +14,8 @@ RSpec.describe ReCaptcha::CheckEnabled, type: :request do describe "ReCaptcha for user actions like Abuse Reports (FeedbackMessages)" do context "when recaptcha SiteConfig keys are not configured" do it "marks ReCaptcha as not enabled regardless of the param passed in" do - allow(SiteConfig).to receive(:recaptcha_site_key).and_return(nil) - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return(nil) + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return(nil) + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return(nil) expect(described_class.call).to be(false) expect(described_class.call(older_user)).to be(false) @@ -24,8 +24,8 @@ RSpec.describe ReCaptcha::CheckEnabled, type: :request do context "when recaptcha SiteConfig keys are configured" do before do - allow(SiteConfig).to receive(:recaptcha_site_key).and_return("someSecretKey") - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return("someSiteKey") + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return("someSecretKey") + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return("someSiteKey") end it "marks ReCaptcha as enabled when logged out (parameter is nil)" do diff --git a/spec/services/re_captcha/check_registration_enabled_spec.rb b/spec/services/re_captcha/check_registration_enabled_spec.rb index a8b010609..019f920b5 100644 --- a/spec/services/re_captcha/check_registration_enabled_spec.rb +++ b/spec/services/re_captcha/check_registration_enabled_spec.rb @@ -4,23 +4,25 @@ RSpec.describe ReCaptcha::CheckRegistrationEnabled, type: :request do describe "ReCaptcha for registration" do context "when recaptcha is enabled" do before do - allow(SiteConfig).to receive(:require_captcha_for_email_password_registration).and_return(true) + allow(Settings::Authentication) + .to receive(:require_captcha_for_email_password_registration).and_return(true) end it "is enabled if both site & secret keys present" do - allow(SiteConfig).to receive(:recaptcha_secret_key).and_return("someSecretKey") - allow(SiteConfig).to receive(:recaptcha_site_key).and_return("someSiteKey") + allow(Settings::Authentication).to receive(:recaptcha_secret_key).and_return("someSecretKey") + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return("someSiteKey") expect(described_class.call).to be(true) end it "is disabled if site or secret key missing" do - allow(SiteConfig).to receive(:recaptcha_site_key).and_return("") + allow(Settings::Authentication).to receive(:recaptcha_site_key).and_return("") expect(described_class.call).to be(false) end end it "is disabled if recaptcha disabled for email signup" do - allow(SiteConfig).to receive(:require_captcha_for_email_password_registration).and_return(false) + allow(Settings::Authentication) + .to receive(:require_captcha_for_email_password_registration).and_return(false) expect(described_class.call).to be(false) end end diff --git a/spec/services/twitter_client/client_spec.rb b/spec/services/twitter_client/client_spec.rb index daefd1ee6..5afc75828 100644 --- a/spec/services/twitter_client/client_spec.rb +++ b/spec/services/twitter_client/client_spec.rb @@ -13,7 +13,7 @@ RSpec.describe TwitterClient::Client, type: :service, vcr: true do it "works properly when SiteConfig is set" do VCR.use_cassette("twitter_client_status") do - allow(SiteConfig).to receive(:twitter_key).and_return("test") + allow(Settings::Authentication).to receive(:twitter_key).and_return("test") tweet = described_class.status(tweet_id) expect(tweet.text).to be_present end diff --git a/spec/services/users/delete_spec.rb b/spec/services/users/delete_spec.rb index 53d686472..10e093cec 100644 --- a/spec/services/users/delete_spec.rb +++ b/spec/services/users/delete_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Users::Delete, type: :service do before do omniauth_mock_github_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) allow(EdgeCache::Bust).to receive(:new).and_return(cache_bust) allow(cache_bust).to receive(:call) end diff --git a/spec/system/authentication/beta_access_providers_spec.rb b/spec/system/authentication/beta_access_providers_spec.rb index 4678d6a1f..c24e2b1b0 100644 --- a/spec/system/authentication/beta_access_providers_spec.rb +++ b/spec/system/authentication/beta_access_providers_spec.rb @@ -5,7 +5,7 @@ RSpec.describe "Beta provider access", type: :system do let(:beta_providers) { ["Apple"] } before do - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end context "when a user tries to sign_up" do diff --git a/spec/system/authentication/creator_config_edit_spec.rb b/spec/system/authentication/creator_config_edit_spec.rb index 20682fc0f..0a80abaa9 100644 --- a/spec/system/authentication/creator_config_edit_spec.rb +++ b/spec/system/authentication/creator_config_edit_spec.rb @@ -9,7 +9,7 @@ RSpec.describe "Creator config edit", type: :system, js: true do context "when a creator browses /admin/config" do before do sign_in admin - allow(SiteConfig).to receive(:invite_only_mode).and_return(false) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(false) end it "presents all available OAuth providers" do diff --git a/spec/system/authentication/omniauth_redirect_uri_spec.rb b/spec/system/authentication/omniauth_redirect_uri_spec.rb index 0391310d1..c1aaa2689 100644 --- a/spec/system/authentication/omniauth_redirect_uri_spec.rb +++ b/spec/system/authentication/omniauth_redirect_uri_spec.rb @@ -20,7 +20,7 @@ RSpec.describe "Omniauth redirect_uri", type: :system do end it "relies on SiteConfig.app_domain to generate correct callbacks_url" do - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) visit sign_up_path Authentication::Providers.available.each do |provider_name| provider_auth_button = find("button.crayons-btn--brand-#{provider_name}") diff --git a/spec/system/authentication/redirects_using_referer_spec.rb b/spec/system/authentication/redirects_using_referer_spec.rb index be6d1740f..7b01b9f61 100644 --- a/spec/system/authentication/redirects_using_referer_spec.rb +++ b/spec/system/authentication/redirects_using_referer_spec.rb @@ -11,7 +11,7 @@ RSpec.describe "Redirects authentication using Referer", type: :system do before do omniauth_mock_twitter_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) OmniAuth.config.mock_auth[:twitter].info.email = user.email end diff --git a/spec/system/authentication/user_logs_in_with_apple_spec.rb b/spec/system/authentication/user_logs_in_with_apple_spec.rb index 3523daf46..bec41bb2b 100644 --- a/spec/system/authentication/user_logs_in_with_apple_spec.rb +++ b/spec/system/authentication/user_logs_in_with_apple_spec.rb @@ -6,7 +6,7 @@ RSpec.describe "Authenticating with Apple", vcr: { cassette_name: "fastly_sloan" before do omniauth_mock_apple_payload Flipper.enable(:apple_auth) - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end context "when a user is new" do diff --git a/spec/system/authentication/user_logs_in_with_email_spec.rb b/spec/system/authentication/user_logs_in_with_email_spec.rb index 1e1d341c3..5d49d8edc 100644 --- a/spec/system/authentication/user_logs_in_with_email_spec.rb +++ b/spec/system/authentication/user_logs_in_with_email_spec.rb @@ -5,8 +5,8 @@ RSpec.describe "Authenticating with Email" do let(:sign_up_link) { "Sign up with Email" } before do - allow(SiteConfig).to receive(:allow_email_password_registration).and_return(true) - allow(SiteConfig).to receive(:allow_email_password_login).and_return(true) + allow(Settings::Authentication).to receive(:allow_email_password_registration).and_return(true) + allow(Settings::Authentication).to receive(:allow_email_password_login).and_return(true) end context "when a user is new" do @@ -112,7 +112,7 @@ RSpec.describe "Authenticating with Email" do context "when community is in invite only mode" do before do - allow(SiteConfig).to receive(:invite_only_mode).and_return(true) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(true) end it "doesn't present the authentication option" do diff --git a/spec/system/authentication/user_logs_in_with_facebook_spec.rb b/spec/system/authentication/user_logs_in_with_facebook_spec.rb index 94db77c45..19cc037e9 100644 --- a/spec/system/authentication/user_logs_in_with_facebook_spec.rb +++ b/spec/system/authentication/user_logs_in_with_facebook_spec.rb @@ -5,7 +5,7 @@ RSpec.describe "Authenticating with Facebook" do before do omniauth_mock_facebook_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end context "when a user is new" do @@ -225,7 +225,7 @@ RSpec.describe "Authenticating with Facebook" do context "when community is in invite only mode" do before do - allow(SiteConfig).to receive(:invite_only_mode).and_return(true) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(true) end it "doesn't present the authentication option" do diff --git a/spec/system/authentication/user_logs_in_with_github_spec.rb b/spec/system/authentication/user_logs_in_with_github_spec.rb index 5778c34c8..f21c5d278 100644 --- a/spec/system/authentication/user_logs_in_with_github_spec.rb +++ b/spec/system/authentication/user_logs_in_with_github_spec.rb @@ -5,7 +5,7 @@ RSpec.describe "Authenticating with GitHub" do before do omniauth_mock_github_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end context "when a user is new" do @@ -191,7 +191,7 @@ RSpec.describe "Authenticating with GitHub" do context "when community is in invite only mode" do before do - allow(SiteConfig).to receive(:invite_only_mode).and_return(true) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(true) end it "doesn't present the authentication option" do diff --git a/spec/system/authentication/user_logs_in_with_twitter_spec.rb b/spec/system/authentication/user_logs_in_with_twitter_spec.rb index 16d17c9e7..a364c5303 100644 --- a/spec/system/authentication/user_logs_in_with_twitter_spec.rb +++ b/spec/system/authentication/user_logs_in_with_twitter_spec.rb @@ -5,7 +5,7 @@ RSpec.describe "Authenticating with Twitter" do before do omniauth_mock_twitter_payload - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) end context "when a user is new" do @@ -183,7 +183,7 @@ RSpec.describe "Authenticating with Twitter" do context "when community is in invite only mode" do before do - allow(SiteConfig).to receive(:invite_only_mode).and_return(true) + allow(Settings::Authentication).to receive(:invite_only_mode).and_return(true) end it "doesn't present the authentication option" do diff --git a/spec/system/authentication/user_with_suspended_username_spec.rb b/spec/system/authentication/user_with_suspended_username_spec.rb index d8e0df34c..747906050 100644 --- a/spec/system/authentication/user_with_suspended_username_spec.rb +++ b/spec/system/authentication/user_with_suspended_username_spec.rb @@ -4,8 +4,8 @@ RSpec.describe "User with suspended username tried to sign up via OAuth" do before do omniauth_mock_twitter_payload - allow(SiteConfig) - .to receive(:authentication_providers) + allow(Settings::Authentication) + .to receive(:providers) .and_return(Authentication::Providers.available) allow(ForemStatsClient).to receive(:increment) diff --git a/spec/system/user_logs_in_with_password_spec.rb b/spec/system/user_logs_in_with_password_spec.rb index 2db7b8c8c..b6fab144d 100644 --- a/spec/system/user_logs_in_with_password_spec.rb +++ b/spec/system/user_logs_in_with_password_spec.rb @@ -11,7 +11,7 @@ RSpec.describe "Authenticating with a password" do let!(:user) { create(:user, password: password, password_confirmation: password) } before do - allow(SiteConfig).to receive(:authentication_providers).and_return(Authentication::Providers.available) + allow(Settings::Authentication).to receive(:providers).and_return(Authentication::Providers.available) visit sign_up_path end diff --git a/vendor/cache/acts_as_follower-06393d3693a1/acts_as_follower.gemspec b/vendor/cache/acts_as_follower-06393d3693a1/acts_as_follower.gemspec index 58e044f2d..b6c96db3e 100644 --- a/vendor/cache/acts_as_follower-06393d3693a1/acts_as_follower.gemspec +++ b/vendor/cache/acts_as_follower-06393d3693a1/acts_as_follower.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Tom Cocca".freeze] - s.date = "2021-03-31" + s.date = "2021-04-09" s.description = "acts_as_follower is a Rubygem to allow any model to follow any other model. This is accomplished through a double polymorphic relationship on the Follow model. There is also built in support for blocking/un-blocking follow records. Main uses would be for Users to follow other Users or for Users to follow Books, etc\u2026 (Basically, to develop the type of follow system that GitHub has)".freeze s.email = ["tom dot cocca at gmail dot com".freeze] s.files = [".gitignore".freeze, ".travis.yml".freeze, "Gemfile".freeze, "MIT-LICENSE".freeze, "README.rdoc".freeze, "Rakefile".freeze, "acts_as_follower.gemspec".freeze, "init.rb".freeze, "lib/acts_as_follower.rb".freeze, "lib/acts_as_follower/follow_scopes.rb".freeze, "lib/acts_as_follower/followable.rb".freeze, "lib/acts_as_follower/follower.rb".freeze, "lib/acts_as_follower/follower_lib.rb".freeze, "lib/acts_as_follower/railtie.rb".freeze, "lib/acts_as_follower/version.rb".freeze, "lib/generators/USAGE".freeze, "lib/generators/acts_as_follower_generator.rb".freeze, "lib/generators/templates/migration.rb".freeze, "lib/generators/templates/model.rb".freeze, "test/README".freeze, "test/acts_as_followable_test.rb".freeze, "test/acts_as_follower_test.rb".freeze, "test/dummy30/Gemfile".freeze, "test/dummy30/Rakefile".freeze, "test/dummy30/app/models/application_record.rb".freeze, "test/dummy30/app/models/band.rb".freeze, "test/dummy30/app/models/band/punk.rb".freeze, "test/dummy30/app/models/band/punk/pop_punk.rb".freeze, "test/dummy30/app/models/custom_record.rb".freeze, "test/dummy30/app/models/some.rb".freeze, "test/dummy30/app/models/user.rb".freeze, "test/dummy30/config.ru".freeze, "test/dummy30/config/application.rb".freeze, "test/dummy30/config/boot.rb".freeze, "test/dummy30/config/database.yml".freeze, "test/dummy30/config/environment.rb".freeze, "test/dummy30/config/environments/development.rb".freeze, "test/dummy30/config/environments/test.rb".freeze, "test/dummy30/config/initializers/backtrace_silencers.rb".freeze, "test/dummy30/config/initializers/inflections.rb".freeze, "test/dummy30/config/initializers/secret_token.rb".freeze, "test/dummy30/config/initializers/session_store.rb".freeze, "test/dummy30/config/locales/en.yml".freeze, "test/dummy30/config/routes.rb".freeze, "test/factories/bands.rb".freeze, "test/factories/somes.rb".freeze, "test/factories/users.rb".freeze, "test/follow_test.rb".freeze, "test/schema.rb".freeze, "test/test_helper.rb".freeze] @@ -16,7 +16,6 @@ Gem::Specification.new do |s| s.licenses = ["MIT".freeze] s.rubygems_version = "3.1.4".freeze s.summary = "A Rubygem to add Follow functionality for ActiveRecord models".freeze - s.test_files = ["test/README".freeze, "test/acts_as_followable_test.rb".freeze, "test/acts_as_follower_test.rb".freeze, "test/dummy30/Gemfile".freeze, "test/dummy30/Rakefile".freeze, "test/dummy30/app/models/application_record.rb".freeze, "test/dummy30/app/models/band.rb".freeze, "test/dummy30/app/models/band/punk.rb".freeze, "test/dummy30/app/models/band/punk/pop_punk.rb".freeze, "test/dummy30/app/models/custom_record.rb".freeze, "test/dummy30/app/models/some.rb".freeze, "test/dummy30/app/models/user.rb".freeze, "test/dummy30/config.ru".freeze, "test/dummy30/config/application.rb".freeze, "test/dummy30/config/boot.rb".freeze, "test/dummy30/config/database.yml".freeze, "test/dummy30/config/environment.rb".freeze, "test/dummy30/config/environments/development.rb".freeze, "test/dummy30/config/environments/test.rb".freeze, "test/dummy30/config/initializers/backtrace_silencers.rb".freeze, "test/dummy30/config/initializers/inflections.rb".freeze, "test/dummy30/config/initializers/secret_token.rb".freeze, "test/dummy30/config/initializers/session_store.rb".freeze, "test/dummy30/config/locales/en.yml".freeze, "test/dummy30/config/routes.rb".freeze, "test/factories/bands.rb".freeze, "test/factories/somes.rb".freeze, "test/factories/users.rb".freeze, "test/follow_test.rb".freeze, "test/schema.rb".freeze, "test/test_helper.rb".freeze] s.installed_by_version = "3.1.4" if s.respond_to? :installed_by_version diff --git a/vendor/cache/ahoy_email-2.0.2.gem b/vendor/cache/ahoy_email-2.0.2.gem deleted file mode 100644 index a831113b9..000000000 Binary files a/vendor/cache/ahoy_email-2.0.2.gem and /dev/null differ diff --git a/vendor/cache/ahoy_email-2.0.3.gem b/vendor/cache/ahoy_email-2.0.3.gem new file mode 100644 index 000000000..523475170 Binary files /dev/null and b/vendor/cache/ahoy_email-2.0.3.gem differ diff --git a/vendor/cache/chartkick-3.4.2.gem b/vendor/cache/chartkick-3.4.2.gem deleted file mode 100644 index efe3b31e1..000000000 Binary files a/vendor/cache/chartkick-3.4.2.gem and /dev/null differ diff --git a/vendor/cache/chartkick-4.0.2.gem b/vendor/cache/chartkick-4.0.2.gem new file mode 100644 index 000000000..f83b2c57a Binary files /dev/null and b/vendor/cache/chartkick-4.0.2.gem differ diff --git a/vendor/cache/devise-0cd72a56f984/devise.gemspec b/vendor/cache/devise-0cd72a56f984/devise.gemspec index b21afef14..0e3a3b9c6 100644 --- a/vendor/cache/devise-0cd72a56f984/devise.gemspec +++ b/vendor/cache/devise-0cd72a56f984/devise.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Jos\u00E9 Valim".freeze, "Carlos Ant\u00F4nio".freeze] - s.date = "2021-03-31" + s.date = "2021-04-09" s.description = "Flexible authentication solution for Rails with Warden".freeze s.email = "heartcombo@googlegroups.com".freeze s.files = ["CHANGELOG.md".freeze, "MIT-LICENSE".freeze, "README.md".freeze, "app/controllers/devise".freeze, "app/controllers/devise/confirmations_controller.rb".freeze, "app/controllers/devise/omniauth_callbacks_controller.rb".freeze, "app/controllers/devise/passwords_controller.rb".freeze, "app/controllers/devise/registrations_controller.rb".freeze, "app/controllers/devise/sessions_controller.rb".freeze, "app/controllers/devise/unlocks_controller.rb".freeze, "app/controllers/devise_controller.rb".freeze, "app/helpers/devise_helper.rb".freeze, "app/mailers/devise".freeze, "app/mailers/devise/mailer.rb".freeze, "app/views/devise/confirmations/new.html.erb".freeze, "app/views/devise/mailer/confirmation_instructions.html.erb".freeze, "app/views/devise/mailer/email_changed.html.erb".freeze, "app/views/devise/mailer/password_change.html.erb".freeze, "app/views/devise/mailer/reset_password_instructions.html.erb".freeze, "app/views/devise/mailer/unlock_instructions.html.erb".freeze, "app/views/devise/passwords/edit.html.erb".freeze, "app/views/devise/passwords/new.html.erb".freeze, "app/views/devise/registrations/edit.html.erb".freeze, "app/views/devise/registrations/new.html.erb".freeze, "app/views/devise/sessions/new.html.erb".freeze, "app/views/devise/shared/_error_messages.html.erb".freeze, "app/views/devise/shared/_links.html.erb".freeze, "app/views/devise/unlocks/new.html.erb".freeze, "config/locales/en.yml".freeze, "lib/devise".freeze, "lib/devise.rb".freeze, "lib/devise/controllers".freeze, "lib/devise/controllers/helpers.rb".freeze, "lib/devise/controllers/rememberable.rb".freeze, "lib/devise/controllers/scoped_views.rb".freeze, "lib/devise/controllers/sign_in_out.rb".freeze, "lib/devise/controllers/store_location.rb".freeze, "lib/devise/controllers/url_helpers.rb".freeze, "lib/devise/delegator.rb".freeze, "lib/devise/encryptor.rb".freeze, "lib/devise/failure_app.rb".freeze, "lib/devise/hooks".freeze, "lib/devise/hooks/activatable.rb".freeze, "lib/devise/hooks/csrf_cleaner.rb".freeze, "lib/devise/hooks/forgetable.rb".freeze, "lib/devise/hooks/lockable.rb".freeze, "lib/devise/hooks/proxy.rb".freeze, "lib/devise/hooks/rememberable.rb".freeze, "lib/devise/hooks/timeoutable.rb".freeze, "lib/devise/hooks/trackable.rb".freeze, "lib/devise/mailers".freeze, "lib/devise/mailers/helpers.rb".freeze, "lib/devise/mapping.rb".freeze, "lib/devise/models".freeze, "lib/devise/models.rb".freeze, "lib/devise/models/authenticatable.rb".freeze, "lib/devise/models/confirmable.rb".freeze, "lib/devise/models/database_authenticatable.rb".freeze, "lib/devise/models/lockable.rb".freeze, "lib/devise/models/omniauthable.rb".freeze, "lib/devise/models/recoverable.rb".freeze, "lib/devise/models/registerable.rb".freeze, "lib/devise/models/rememberable.rb".freeze, "lib/devise/models/timeoutable.rb".freeze, "lib/devise/models/trackable.rb".freeze, "lib/devise/models/validatable.rb".freeze, "lib/devise/modules.rb".freeze, "lib/devise/omniauth".freeze, "lib/devise/omniauth.rb".freeze, "lib/devise/omniauth/config.rb".freeze, "lib/devise/omniauth/url_helpers.rb".freeze, "lib/devise/orm".freeze, "lib/devise/orm/active_record.rb".freeze, "lib/devise/orm/mongoid.rb".freeze, "lib/devise/parameter_filter.rb".freeze, "lib/devise/parameter_sanitizer.rb".freeze, "lib/devise/rails".freeze, "lib/devise/rails.rb".freeze, "lib/devise/rails/deprecated_constant_accessor.rb".freeze, "lib/devise/rails/routes.rb".freeze, "lib/devise/rails/warden_compat.rb".freeze, "lib/devise/secret_key_finder.rb".freeze, "lib/devise/strategies".freeze, "lib/devise/strategies/authenticatable.rb".freeze, "lib/devise/strategies/base.rb".freeze, "lib/devise/strategies/database_authenticatable.rb".freeze, "lib/devise/strategies/rememberable.rb".freeze, "lib/devise/test".freeze, "lib/devise/test/controller_helpers.rb".freeze, "lib/devise/test/integration_helpers.rb".freeze, "lib/devise/test_helpers.rb".freeze, "lib/devise/time_inflector.rb".freeze, "lib/devise/token_generator.rb".freeze, "lib/devise/version.rb".freeze, "lib/generators/active_record".freeze, "lib/generators/active_record/devise_generator.rb".freeze, "lib/generators/active_record/templates".freeze, "lib/generators/active_record/templates/migration.rb".freeze, "lib/generators/active_record/templates/migration_existing.rb".freeze, "lib/generators/devise".freeze, "lib/generators/devise/controllers_generator.rb".freeze, "lib/generators/devise/devise_generator.rb".freeze, "lib/generators/devise/install_generator.rb".freeze, "lib/generators/devise/orm_helpers.rb".freeze, "lib/generators/devise/views_generator.rb".freeze, "lib/generators/mongoid".freeze, "lib/generators/mongoid/devise_generator.rb".freeze, "lib/generators/templates".freeze, "lib/generators/templates/README".freeze, "lib/generators/templates/controllers".freeze, "lib/generators/templates/controllers/README".freeze, "lib/generators/templates/controllers/confirmations_controller.rb".freeze, "lib/generators/templates/controllers/omniauth_callbacks_controller.rb".freeze, "lib/generators/templates/controllers/passwords_controller.rb".freeze, "lib/generators/templates/controllers/registrations_controller.rb".freeze, "lib/generators/templates/controllers/sessions_controller.rb".freeze, "lib/generators/templates/controllers/unlocks_controller.rb".freeze, "lib/generators/templates/devise.rb".freeze, "lib/generators/templates/markerb".freeze, "lib/generators/templates/markerb/confirmation_instructions.markerb".freeze, "lib/generators/templates/markerb/email_changed.markerb".freeze, "lib/generators/templates/markerb/password_change.markerb".freeze, "lib/generators/templates/markerb/reset_password_instructions.markerb".freeze, "lib/generators/templates/markerb/unlock_instructions.markerb".freeze, "lib/generators/templates/simple_form_for".freeze, "lib/generators/templates/simple_form_for/confirmations".freeze, "lib/generators/templates/simple_form_for/confirmations/new.html.erb".freeze, "lib/generators/templates/simple_form_for/passwords".freeze, "lib/generators/templates/simple_form_for/passwords/edit.html.erb".freeze, "lib/generators/templates/simple_form_for/passwords/new.html.erb".freeze, "lib/generators/templates/simple_form_for/registrations".freeze, "lib/generators/templates/simple_form_for/registrations/edit.html.erb".freeze, "lib/generators/templates/simple_form_for/registrations/new.html.erb".freeze, "lib/generators/templates/simple_form_for/sessions".freeze, "lib/generators/templates/simple_form_for/sessions/new.html.erb".freeze, "lib/generators/templates/simple_form_for/unlocks".freeze, "lib/generators/templates/simple_form_for/unlocks/new.html.erb".freeze] diff --git a/vendor/cache/loofah-2.9.0.gem b/vendor/cache/loofah-2.9.0.gem deleted file mode 100644 index ca1d43599..000000000 Binary files a/vendor/cache/loofah-2.9.0.gem and /dev/null differ diff --git a/vendor/cache/loofah-2.9.1.gem b/vendor/cache/loofah-2.9.1.gem new file mode 100644 index 000000000..0cba393f2 Binary files /dev/null and b/vendor/cache/loofah-2.9.1.gem differ diff --git a/vendor/cache/marcel-1.0.0.gem b/vendor/cache/marcel-1.0.0.gem deleted file mode 100644 index ae0e4ee08..000000000 Binary files a/vendor/cache/marcel-1.0.0.gem and /dev/null differ diff --git a/vendor/cache/marcel-1.0.1.gem b/vendor/cache/marcel-1.0.1.gem new file mode 100644 index 000000000..0ad605c80 Binary files /dev/null and b/vendor/cache/marcel-1.0.1.gem differ diff --git a/vendor/cache/oauth-0.5.5.gem b/vendor/cache/oauth-0.5.5.gem deleted file mode 100644 index 099825304..000000000 Binary files a/vendor/cache/oauth-0.5.5.gem and /dev/null differ diff --git a/vendor/cache/oauth-0.5.6.gem b/vendor/cache/oauth-0.5.6.gem new file mode 100644 index 000000000..ed6eedd9e Binary files /dev/null and b/vendor/cache/oauth-0.5.6.gem differ diff --git a/vendor/cache/parser-3.0.0.0.gem b/vendor/cache/parser-3.0.0.0.gem deleted file mode 100644 index f542329d6..000000000 Binary files a/vendor/cache/parser-3.0.0.0.gem and /dev/null differ diff --git a/vendor/cache/parser-3.0.1.0.gem b/vendor/cache/parser-3.0.1.0.gem new file mode 100644 index 000000000..7e551581f Binary files /dev/null and b/vendor/cache/parser-3.0.1.0.gem differ