mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 11:37:58 +00:00
chore: Reorganize the installation config settings (#8794)
- Reorganizing installation config settings to move more configurations into UI from environment variables - Changes to installation config to support premium plans in the enterprise edition - Fixes the broken premium indicator in account/show and accounts/edit page
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
margin-right: 4px;
|
margin-right: 2px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,19 +22,24 @@ class SuperAdmin::AppConfigsController < SuperAdmin::ApplicationController
|
|||||||
i.value = value
|
i.value = value
|
||||||
i.save!
|
i.save!
|
||||||
end
|
end
|
||||||
# rubocop:disable Rails/I18nLocaleTexts
|
redirect_to super_admin_settings_path, notice: "App Configs - #{@config.titleize} updated successfully"
|
||||||
redirect_to super_admin_settings_path, notice: 'App Configs updated successfully'
|
|
||||||
# rubocop:enable Rails/I18nLocaleTexts
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_config
|
def set_config
|
||||||
@config = params[:config]
|
@config = params[:config] || 'general'
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_configs
|
def allowed_configs
|
||||||
@allowed_configs = %w[FB_APP_ID FB_VERIFY_TOKEN FB_APP_SECRET]
|
@allowed_configs = case @config
|
||||||
|
when 'facebook'
|
||||||
|
%w[FB_APP_ID FB_VERIFY_TOKEN FB_APP_SECRET IG_VERIFY_TOKEN ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT]
|
||||||
|
when 'email'
|
||||||
|
['MAILER_INBOUND_EMAIL_DOMAIN']
|
||||||
|
else
|
||||||
|
%w[ENABLE_ACCOUNT_SIGNUP]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
9
app/helpers/super_admin/account_features_helper.rb
Normal file
9
app/helpers/super_admin/account_features_helper.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module SuperAdmin::AccountFeaturesHelper
|
||||||
|
def self.account_features
|
||||||
|
YAML.safe_load(Rails.root.join('config/features.yml').read).freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.account_premium_features
|
||||||
|
account_features.filter { |feature| feature['premium'] }.pluck('name')
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -4,21 +4,17 @@ class Internal::CheckNewVersionsJob < ApplicationJob
|
|||||||
def perform
|
def perform
|
||||||
return unless Rails.env.production?
|
return unless Rails.env.production?
|
||||||
|
|
||||||
instance_info = ChatwootHub.sync_with_hub
|
@instance_info = ChatwootHub.sync_with_hub
|
||||||
return unless instance_info
|
update_version_info
|
||||||
|
|
||||||
::Redis::Alfred.set(::Redis::Alfred::LATEST_CHATWOOT_VERSION, instance_info['version'])
|
|
||||||
update_installation_config(key: 'INSTALLATION_PRICING_PLAN', value: instance_info['plan'])
|
|
||||||
update_installation_config(key: 'INSTALLATION_PRICING_PLAN_QUANTITY', value: instance_info['plan_quantity'])
|
|
||||||
update_installation_config(key: 'CHATWOOT_SUPPORT_WEBSITE_TOKEN', value: instance_info['chatwoot_support_website_token'])
|
|
||||||
update_installation_config(key: 'CHATWOOT_SUPPORT_IDENTIFIER_HASH', value: instance_info['chatwoot_support_identifier_hash'])
|
|
||||||
update_installation_config(key: 'CHATWOOT_SUPPORT_SCRIPT_URL', value: instance_info['chatwoot_support_script_url'])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_installation_config(key:, value:)
|
private
|
||||||
config = InstallationConfig.find_or_initialize_by(name: key)
|
|
||||||
config.value = value
|
def update_version_info
|
||||||
config.locked = true
|
return if @instance_info['version'].blank?
|
||||||
config.save!
|
|
||||||
|
::Redis::Alfred.set(::Redis::Alfred::LATEST_CHATWOOT_VERSION, @instance_info['version'])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Internal::CheckNewVersionsJob.prepend_mod_with('Internal::CheckNewVersionsJob')
|
||||||
|
|||||||
@@ -4,11 +4,15 @@
|
|||||||
<div class="field-unit__field feature-container">
|
<div class="field-unit__field feature-container">
|
||||||
<% field.data.each do |key,val| %>
|
<% field.data.each do |key,val| %>
|
||||||
<div class='feature-cell'>
|
<div class='feature-cell'>
|
||||||
<% if ['audit_logs', 'response_bot'].include? key %>
|
<% is_premium = SuperAdmin::AccountFeaturesHelper.account_premium_features.include? key %>
|
||||||
<span class='icon-container'><i class="ion ion-asterisk"></i></span>
|
<% if is_premium %>
|
||||||
|
<span class='icon-container'>
|
||||||
|
<svg class="inline" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"><path d="M480 224l-186.828 7.487L401.688 64l-59.247-32L256 208 169.824 32l-59.496 32 108.5 167.487L32 224v64l185.537-10.066L113.65 448l55.969 32L256 304l86.381 176 55.949-32-103.867-170.066L480 288z" fill="currentColor"/></svg>
|
||||||
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<span><%= key %></span>
|
<span><%= key %></span>
|
||||||
<span class='value-container'><%= check_box "enabled_features", "feature_#{key}", { checked: val }, true, false %> </span>
|
<% should_disable = is_premium && ChatwootHub.pricing_plan == 'community' %>
|
||||||
|
<span class='value-container'><%= check_box "enabled_features", "feature_#{key}", { checked: val, disabled: should_disable }, true, false %> </span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<div class='feature-container'>
|
<div class='feature-container'>
|
||||||
<% field.data.each do |key,val| %>
|
<% field.data.each do |key,val| %>
|
||||||
<div class='feature-cell'>
|
<div class='feature-cell'>
|
||||||
<% if ['audit_logs', 'response_bot'].include? key %>
|
<% if SuperAdmin::AccountFeaturesHelper.account_premium_features.include? key %>
|
||||||
<span class='icon-container'><i class="ion ion-asterisk"></i></span>
|
<span class='icon-container'>
|
||||||
|
<svg class="inline" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"><path d="M480 224l-186.828 7.487L401.688 64l-59.247-32L256 208 169.824 32l-59.496 32 108.5 167.487L32 224v64l185.537-10.066L113.65 448l55.969 32L256 304l86.381 176 55.949-32-103.867-170.066L480 288z" fill="currentColor"/></svg>
|
||||||
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<span><%= key %></span>
|
<span><%= key %></span>
|
||||||
<span class='value-container'><%= val.present? ? '✅' : '❌' %> </span>
|
<span class='value-container'><%= val.present? ? '✅' : '❌' %> </span>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<% content_for(:title) do %>
|
<% content_for(:title) do %>
|
||||||
Configure Settings
|
Configure Settings - <%= @config.titleize %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<header class="main-content__header" role="banner">
|
<header class="main-content__header" role="banner">
|
||||||
<h1 class="main-content__page-title" id="page-title">
|
<h1 class="main-content__page-title" id="page-title">
|
||||||
|
|||||||
@@ -13,6 +13,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<section class="main-content__body">
|
<section class="main-content__body">
|
||||||
|
|
||||||
|
<% if Redis::Alfred.get(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING) %>
|
||||||
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-5" role="alert">
|
||||||
|
<strong class="font-bold">Alert!</strong>
|
||||||
|
<span class="block sm:inline">Unauthorized premium changes detected in Chatwoot. To keep using them, please upgrade your plan.
|
||||||
|
Contact for help :</span><span class="inline rounded-full bg-red-200 px-2 text-white ml-2">sales@chatwoot.com</span>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<div class="bg-white py-2 px-3">
|
<div class="bg-white py-2 px-3">
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -44,7 +53,7 @@
|
|||||||
<% if ChatwootHub.pricing_plan != 'community' && User.count > ChatwootHub.pricing_plan_quantity %>
|
<% if ChatwootHub.pricing_plan != 'community' && User.count > ChatwootHub.pricing_plan_quantity %>
|
||||||
<div role="alert">
|
<div role="alert">
|
||||||
<div class="border border-t-0 border-red-400 rounded-b bg-red-100 px-4 py-3 text-red-700">
|
<div class="border border-t-0 border-red-400 rounded-b bg-red-100 px-4 py-3 text-red-700">
|
||||||
<p>You have <%= User.count %> agents. Please add more licenses.</p>
|
<p>You have <%= User.count %> agents. Please add more licenses to add more users.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
enabled: false
|
enabled: false
|
||||||
- name: disable_branding
|
- name: disable_branding
|
||||||
enabled: false
|
enabled: false
|
||||||
|
premium: true
|
||||||
- name: email_continuity_on_api_channel
|
- name: email_continuity_on_api_channel
|
||||||
enabled: false
|
enabled: false
|
||||||
- name: help_center
|
- name: help_center
|
||||||
@@ -55,8 +56,10 @@
|
|||||||
enabled: false
|
enabled: false
|
||||||
- name: audit_logs
|
- name: audit_logs
|
||||||
enabled: false
|
enabled: false
|
||||||
|
premium: true
|
||||||
- name: response_bot
|
- name: response_bot
|
||||||
enabled: false
|
enabled: false
|
||||||
|
premium: true
|
||||||
- name: message_reply_to
|
- name: message_reply_to
|
||||||
enabled: false
|
enabled: false
|
||||||
- name: insert_article_in_reply
|
- name: insert_article_in_reply
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
# if you don't specify locked attribute, the default value will be true
|
# This file contains all the installation wide configuration which controls various settings in Chatwoot
|
||||||
# which means the particular config will be locked
|
# This is internal config and should not be modified by the user directly in database
|
||||||
|
# Chatwoot might override and modify these values during the upgrade process
|
||||||
|
# Configs which can be modified by the user are available in the dashboard under appropriate UI
|
||||||
|
#
|
||||||
|
# name: the name of the config referenced in the code
|
||||||
|
# value: the value of the config
|
||||||
|
# display_title: the title of the config displayed in the dashboard UI
|
||||||
|
# description: the description of the config displayed in the dashboard UI
|
||||||
|
# locked: if you don't specify locked attribute in yaml, the default value will be true,
|
||||||
|
# which means the particular config will be locked and won't be available in `super_admin/installation_configs`
|
||||||
|
# premium: These values get overwritten unless the user is on a premium plan
|
||||||
|
# type: The type of the config. Default is text, boolean is also supported
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------- Branding Related Config ------- #
|
||||||
- name: INSTALLATION_NAME
|
- name: INSTALLATION_NAME
|
||||||
value: 'Chatwoot'
|
value: 'Chatwoot'
|
||||||
display_title: 'Installation Name'
|
display_title: 'Installation Name'
|
||||||
@@ -41,32 +56,20 @@
|
|||||||
display_title: 'Chatwoot Metadata'
|
display_title: 'Chatwoot Metadata'
|
||||||
description: 'Display default Chatwoot metadata like favicons and upgrade warnings'
|
description: 'Display default Chatwoot metadata like favicons and upgrade warnings'
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: MAILER_INBOUND_EMAIL_DOMAIN
|
# ------- End of Branding Related Config ------- #
|
||||||
value:
|
|
||||||
locked: false
|
|
||||||
- name: MAILER_SUPPORT_EMAIL
|
|
||||||
value:
|
# ------- Signup & Account Related Config ------- #
|
||||||
|
- name: ENABLE_ACCOUNT_SIGNUP
|
||||||
|
display_title: 'Enable Account Signup'
|
||||||
|
value: false
|
||||||
|
description: 'Allow users to signup for new accounts'
|
||||||
locked: false
|
locked: false
|
||||||
|
type: boolean
|
||||||
- name: CREATE_NEW_ACCOUNT_FROM_DASHBOARD
|
- name: CREATE_NEW_ACCOUNT_FROM_DASHBOARD
|
||||||
value: false
|
value: false
|
||||||
locked: false
|
description: 'Allow users to create new accounts from the dashboard'
|
||||||
- name: INSTALLATION_EVENTS_WEBHOOK_URL
|
|
||||||
value:
|
|
||||||
locked: false
|
|
||||||
- name: CHATWOOT_INBOX_TOKEN
|
|
||||||
value:
|
|
||||||
locked: false
|
|
||||||
- name: CHATWOOT_INBOX_HMAC_KEY
|
|
||||||
value:
|
|
||||||
locked: false
|
|
||||||
- name: API_CHANNEL_NAME
|
|
||||||
value:
|
|
||||||
- name: API_CHANNEL_THUMBNAIL
|
|
||||||
value:
|
|
||||||
- name: ANALYTICS_TOKEN
|
|
||||||
value:
|
|
||||||
- name: DIRECT_UPLOADS_ENABLED
|
|
||||||
value: false
|
|
||||||
locked: false
|
locked: false
|
||||||
- name: HCAPTCHA_SITE_KEY
|
- name: HCAPTCHA_SITE_KEY
|
||||||
value:
|
value:
|
||||||
@@ -74,34 +77,107 @@
|
|||||||
- name: HCAPTCHA_SERVER_KEY
|
- name: HCAPTCHA_SERVER_KEY
|
||||||
value:
|
value:
|
||||||
locked: false
|
locked: false
|
||||||
- name: LOGOUT_REDIRECT_LINK
|
- name: INSTALLATION_EVENTS_WEBHOOK_URL
|
||||||
value: /app/login
|
value:
|
||||||
|
display_title: 'System events Webhook URL'
|
||||||
|
description: 'The URL to which the system events like new accounts created will be sent'
|
||||||
locked: false
|
locked: false
|
||||||
- name: DISABLE_USER_PROFILE_UPDATE
|
- name: DIRECT_UPLOADS_ENABLED
|
||||||
|
type: boolean
|
||||||
value: false
|
value: false
|
||||||
|
description: 'Enable direct uploads to cloud storage'
|
||||||
|
locked: false
|
||||||
|
# ------- End of Account Related Config ------- #
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------- Email Related Config ------- #
|
||||||
|
- name: MAILER_INBOUND_EMAIL_DOMAIN
|
||||||
|
value:
|
||||||
|
description: 'The domain name to be used for generating conversation continuity emails (reply+id@domain.com)'
|
||||||
|
locked: false
|
||||||
|
- name: MAILER_SUPPORT_EMAIL
|
||||||
|
value:
|
||||||
|
locked: false
|
||||||
|
# ------- End of Email Related Config ------- #
|
||||||
|
|
||||||
|
|
||||||
|
# ------- Facebook Channel Related Config ------- #
|
||||||
|
- name: FB_APP_ID
|
||||||
|
display_title: 'Facebook App ID'
|
||||||
|
locked: false
|
||||||
|
- name: FB_VERIFY_TOKEN
|
||||||
|
display_title: 'Facebook Verify Token'
|
||||||
|
description: 'The verify token used for Facebook Messenger Webhook'
|
||||||
|
locked: false
|
||||||
|
- name: FB_APP_SECRET
|
||||||
|
display_title: 'Facebook App Secret'
|
||||||
|
locked: false
|
||||||
|
- name: IG_VERIFY_TOKEN
|
||||||
|
display_title: 'Instagram Verify Token'
|
||||||
|
description: 'The verify token used for Instagram Webhook'
|
||||||
locked: false
|
locked: false
|
||||||
- name: ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT
|
- name: ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT
|
||||||
|
display_title: 'Enable human agent'
|
||||||
value: false
|
value: false
|
||||||
locked: false
|
locked: false
|
||||||
- name: CSML_BOT_HOST
|
description: 'Enable human agent for messenger channel for longer message back period. Needs additional app approval: https://developers.facebook.com/docs/features-reference/human-agent/'
|
||||||
|
type: boolean
|
||||||
|
# ------- End of Facebook Channel Related Config ------- #
|
||||||
|
|
||||||
|
# ------- Chatwoot Internal Config for Cloud ----#
|
||||||
|
- name: CHATWOOT_INBOX_TOKEN
|
||||||
value:
|
value:
|
||||||
|
description: 'The Chatwoot Inbox Token for Contact Support in Cloud'
|
||||||
locked: false
|
locked: false
|
||||||
- name: CSML_BOT_API_KEY
|
- name: CHATWOOT_INBOX_HMAC_KEY
|
||||||
value:
|
value:
|
||||||
|
description: 'The Chatwoot Inbox HMAC Key for Contact Support in Cloud'
|
||||||
locked: false
|
locked: false
|
||||||
- name: CHATWOOT_CLOUD_PLANS
|
- name: CHATWOOT_CLOUD_PLANS
|
||||||
value:
|
value:
|
||||||
|
description: 'Config to store stripe plans for cloud'
|
||||||
- name: DEPLOYMENT_ENV
|
- name: DEPLOYMENT_ENV
|
||||||
value: self-hosted
|
value: self-hosted
|
||||||
- name: CSML_EDITOR_HOST
|
description: 'The deployment environment of the installation, to differentiate between Chatwoot cloud and self-hosted'
|
||||||
|
- name: ANALYTICS_TOKEN
|
||||||
value:
|
value:
|
||||||
|
description: 'The June.so analytics token for Chatwoot cloud'
|
||||||
|
# ------- End of Chatwoot Internal Config for Cloud ----#
|
||||||
|
|
||||||
|
|
||||||
|
# ------- Chatwoot Internal Config for Self Hosted ----#
|
||||||
- name: INSTALLATION_PRICING_PLAN
|
- name: INSTALLATION_PRICING_PLAN
|
||||||
value: 'community'
|
value: 'community'
|
||||||
|
description: 'The pricing plan for the installation, retrieved from the billing API'
|
||||||
- name: INSTALLATION_PRICING_PLAN_QUANTITY
|
- name: INSTALLATION_PRICING_PLAN_QUANTITY
|
||||||
value: 0
|
value: 0
|
||||||
|
description: 'The number of licenses purchased for the installation, retrieved from the billing API'
|
||||||
- name: CHATWOOT_SUPPORT_WEBSITE_TOKEN
|
- name: CHATWOOT_SUPPORT_WEBSITE_TOKEN
|
||||||
value:
|
value:
|
||||||
|
description: 'The Chatwoot website token, used to identify the Chatwoot inbox and display the "Contact Support" option on the billing page'
|
||||||
- name: CHATWOOT_SUPPORT_SCRIPT_URL
|
- name: CHATWOOT_SUPPORT_SCRIPT_URL
|
||||||
value:
|
value:
|
||||||
|
description: 'The Chatwoot script base URL, to display the "Contact Support" option on the billing page'
|
||||||
- name: CHATWOOT_SUPPORT_IDENTIFIER_HASH
|
- name: CHATWOOT_SUPPORT_IDENTIFIER_HASH
|
||||||
value:
|
value:
|
||||||
|
description: 'The Chatwoot identifier hash, to validate the contact in the live chat window.'
|
||||||
|
# ------- End of Chatwoot Internal Config for Self Hosted ----#
|
||||||
|
|
||||||
|
## ------ Configs added for enterprise clients ------ ##
|
||||||
|
- name: API_CHANNEL_NAME
|
||||||
|
value:
|
||||||
|
description: 'Custom name for the API channel'
|
||||||
|
- name: API_CHANNEL_THUMBNAIL
|
||||||
|
value:
|
||||||
|
description: 'Custom thumbnail for the API channel'
|
||||||
|
- name: LOGOUT_REDIRECT_LINK
|
||||||
|
value: /app/login
|
||||||
|
locked: false
|
||||||
|
description: 'Redirect to a different link after logout'
|
||||||
|
- name: DISABLE_USER_PROFILE_UPDATE
|
||||||
|
value: false
|
||||||
|
locked: false
|
||||||
|
description: 'Disable rendering profile update page for users'
|
||||||
|
|
||||||
|
## ------ End of Configs added for enterprise clients ------ ##
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# TODO: Move this values to features.yml itself
|
||||||
|
# No need to replicate the same values in two places
|
||||||
custom_branding:
|
custom_branding:
|
||||||
name: 'Custom Branding'
|
name: 'Custom Branding'
|
||||||
description: 'Apply your own branding to this installation.'
|
description: 'Apply your own branding to this installation.'
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
module Enterprise::Internal::CheckNewVersionsJob
|
||||||
|
def perform
|
||||||
|
super
|
||||||
|
update_plan_info
|
||||||
|
reconcile_premium_config_and_features
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def update_plan_info
|
||||||
|
return if @instance_info.blank?
|
||||||
|
|
||||||
|
update_installation_config(key: 'INSTALLATION_PRICING_PLAN', value: @instance_info['plan'])
|
||||||
|
update_installation_config(key: 'INSTALLATION_PRICING_PLAN_QUANTITY', value: @instance_info['plan_quantity'])
|
||||||
|
update_installation_config(key: 'CHATWOOT_SUPPORT_WEBSITE_TOKEN', value: @instance_info['chatwoot_support_website_token'])
|
||||||
|
update_installation_config(key: 'CHATWOOT_SUPPORT_IDENTIFIER_HASH', value: @instance_info['chatwoot_support_identifier_hash'])
|
||||||
|
update_installation_config(key: 'CHATWOOT_SUPPORT_SCRIPT_URL', value: @instance_info['chatwoot_support_script_url'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_installation_config(key:, value:)
|
||||||
|
config = InstallationConfig.find_or_initialize_by(name: key)
|
||||||
|
config.value = value
|
||||||
|
config.locked = true
|
||||||
|
config.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def reconcile_premium_config_and_features
|
||||||
|
Internal::ReconcilePlanConfigService.new.perform
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
class Internal::ReconcilePlanConfigService
|
||||||
|
def perform
|
||||||
|
remove_premium_config_reset_warning
|
||||||
|
return if ChatwootHub.pricing_plan != 'community'
|
||||||
|
|
||||||
|
create_premium_config_reset_warning if premium_config_reset_required?
|
||||||
|
|
||||||
|
# We will have this enabled in the future
|
||||||
|
# reconcile_premium_config
|
||||||
|
reconcile_premium_features
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def config_path
|
||||||
|
@config_path ||= Rails.root.join('enterprise/config')
|
||||||
|
end
|
||||||
|
|
||||||
|
def premium_config
|
||||||
|
@premium_config ||= YAML.safe_load(File.read("#{config_path}/premium_installation_config.yml")).freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_premium_config_reset_warning
|
||||||
|
Redis::Alfred.delete(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_premium_config_reset_warning
|
||||||
|
Redis::Alfred.set(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def premium_config_reset_required?
|
||||||
|
premium_config.any? do |config|
|
||||||
|
config = config.with_indifferent_access
|
||||||
|
existing_config = InstallationConfig.find_by(name: config[:name])
|
||||||
|
existing_config&.value != config[:value] if existing_config.present?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def reconcile_premium_config
|
||||||
|
premium_config.each do |config|
|
||||||
|
new_config = config.with_indifferent_access
|
||||||
|
existing_config = InstallationConfig.find_by(name: new_config[:name])
|
||||||
|
next if existing_config&.value == new_config[:value]
|
||||||
|
|
||||||
|
existing_config&.update!(value: new_config[:value])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def premium_features
|
||||||
|
@premium_features ||= YAML.safe_load(File.read("#{config_path}/premium_features.yml")).freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def reconcile_premium_features
|
||||||
|
Account.find_in_batches do |accounts|
|
||||||
|
accounts.each do |account|
|
||||||
|
account.disable_features!(*premium_features)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
4
enterprise/config/premium_features.yml
Normal file
4
enterprise/config/premium_features.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# List of the premium features in EE edition
|
||||||
|
- disable_branding
|
||||||
|
- audit_logs
|
||||||
|
- response_bot
|
||||||
22
enterprise/config/premium_installation_config.yml
Normal file
22
enterprise/config/premium_installation_config.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# ------- Branding Related Config ------- #
|
||||||
|
- name: INSTALLATION_NAME
|
||||||
|
value: 'Chatwoot'
|
||||||
|
- name: LOGO_THUMBNAIL
|
||||||
|
value: '/brand-assets/logo_thumbnail.svg'
|
||||||
|
- name: LOGO
|
||||||
|
value: '/brand-assets/logo.svg'
|
||||||
|
- name: LOGO_DARK
|
||||||
|
value: '/brand-assets/logo_dark.svg'
|
||||||
|
- name: BRAND_URL
|
||||||
|
value: 'https://www.chatwoot.com'
|
||||||
|
- name: WIDGET_BRAND_URL
|
||||||
|
value: 'https://www.chatwoot.com'
|
||||||
|
- name: BRAND_NAME
|
||||||
|
value: 'Chatwoot'
|
||||||
|
- name: TERMS_URL
|
||||||
|
value: 'https://www.chatwoot.com/terms-of-service'
|
||||||
|
- name: PRIVACY_URL
|
||||||
|
value: 'https://www.chatwoot.com/privacy-policy'
|
||||||
|
- name: DISPLAY_MANIFEST
|
||||||
|
value: true
|
||||||
|
# ------- End of Branding Related Config ------- #
|
||||||
@@ -28,6 +28,7 @@ module Redis::RedisKeys
|
|||||||
|
|
||||||
## Internal Installation related keys
|
## Internal Installation related keys
|
||||||
CHATWOOT_INSTALLATION_ONBOARDING = 'CHATWOOT_INSTALLATION_ONBOARDING'.freeze
|
CHATWOOT_INSTALLATION_ONBOARDING = 'CHATWOOT_INSTALLATION_ONBOARDING'.freeze
|
||||||
|
CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING = 'CHATWOOT_CONFIG_RESET_WARNING'.freeze
|
||||||
LATEST_CHATWOOT_VERSION = 'LATEST_CHATWOOT_VERSION'.freeze
|
LATEST_CHATWOOT_VERSION = 'LATEST_CHATWOOT_VERSION'.freeze
|
||||||
# Check if a message create with same source-id is in progress?
|
# Check if a message create with same source-id is in progress?
|
||||||
MESSAGE_SOURCE_KEY = 'MESSAGE_SOURCE_KEY::%<id>s'.freeze
|
MESSAGE_SOURCE_KEY = 'MESSAGE_SOURCE_KEY::%<id>s'.freeze
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ RSpec.describe 'Super Admin Application Config API', type: :request do
|
|||||||
|
|
||||||
it 'shows the app_config page' do
|
it 'shows the app_config page' do
|
||||||
sign_in(super_admin, scope: :super_admin)
|
sign_in(super_admin, scope: :super_admin)
|
||||||
get '/super_admin/app_config'
|
get '/super_admin/app_config?config=facebook'
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(response.body).to include(config.name)
|
expect(response.body).to include(config.value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -34,7 +34,7 @@ RSpec.describe 'Super Admin Application Config API', type: :request do
|
|||||||
context 'when it is an aunthenticated super admin' do
|
context 'when it is an aunthenticated super admin' do
|
||||||
it 'shows the app_config page' do
|
it 'shows the app_config page' do
|
||||||
sign_in(super_admin, scope: :super_admin)
|
sign_in(super_admin, scope: :super_admin)
|
||||||
post '/super_admin/app_config', params: { app_config: { FB_APP_ID: 'FB_APP_ID' } }
|
post '/super_admin/app_config?config=facebook', params: { app_config: { FB_APP_ID: 'FB_APP_ID' } }
|
||||||
|
|
||||||
expect(response).to have_http_status(:found)
|
expect(response).to have_http_status(:found)
|
||||||
expect(response).to redirect_to(super_admin_settings_path)
|
expect(response).to redirect_to(super_admin_settings_path)
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Internal::CheckNewVersionsJob do
|
||||||
|
subject(:job) { described_class.perform_now }
|
||||||
|
|
||||||
|
let(:reconsile_premium_config_service) { instance_double(Internal::ReconcilePlanConfigService) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Internal::ReconcilePlanConfigService).to receive(:new).and_return(reconsile_premium_config_service)
|
||||||
|
allow(reconsile_premium_config_service).to receive(:perform)
|
||||||
|
allow(Rails.env).to receive(:production?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the plan info' do
|
||||||
|
data = { 'version' => '1.2.3', 'plan' => 'enterprise', 'plan_quantity' => 1, 'chatwoot_support_website_token' => '123',
|
||||||
|
'chatwoot_support_identifier_hash' => '123', 'chatwoot_support_script_url' => '123' }
|
||||||
|
allow(ChatwootHub).to receive(:sync_with_hub).and_return(data)
|
||||||
|
job
|
||||||
|
expect(InstallationConfig.find_by(name: 'INSTALLATION_PRICING_PLAN').value).to eq 'enterprise'
|
||||||
|
expect(InstallationConfig.find_by(name: 'INSTALLATION_PRICING_PLAN_QUANTITY').value).to eq 1
|
||||||
|
expect(InstallationConfig.find_by(name: 'CHATWOOT_SUPPORT_WEBSITE_TOKEN').value).to eq '123'
|
||||||
|
expect(InstallationConfig.find_by(name: 'CHATWOOT_SUPPORT_IDENTIFIER_HASH').value).to eq '123'
|
||||||
|
expect(InstallationConfig.find_by(name: 'CHATWOOT_SUPPORT_SCRIPT_URL').value).to eq '123'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls Internal::ReconcilePlanConfigService' do
|
||||||
|
data = { 'version' => '1.2.3' }
|
||||||
|
allow(ChatwootHub).to receive(:sync_with_hub).and_return(data)
|
||||||
|
job
|
||||||
|
expect(reconsile_premium_config_service).to have_received(:perform)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Internal::ReconcilePlanConfigService do
|
||||||
|
describe '#perform' do
|
||||||
|
let(:service) { described_class.new }
|
||||||
|
|
||||||
|
context 'when pricing plan is community' do
|
||||||
|
before do
|
||||||
|
allow(ChatwootHub).to receive(:pricing_plan).and_return('community')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'disables the premium features for accounts' do
|
||||||
|
account = create(:account)
|
||||||
|
account.enable_features!('disable_branding', 'audit_logs', 'response_bot')
|
||||||
|
response_bot_account = create(:account)
|
||||||
|
response_bot_account.enable_features!('response_bot')
|
||||||
|
disable_branding_account = create(:account)
|
||||||
|
disable_branding_account.enable_features!('disable_branding')
|
||||||
|
service.perform
|
||||||
|
expect(account.reload.enabled_features.keys).not_to include('response_bot', 'disable_branding', 'audit_logs')
|
||||||
|
expect(response_bot_account.reload.enabled_features.keys).not_to include('response_bot')
|
||||||
|
expect(disable_branding_account.reload.enabled_features.keys).not_to include('disable_branding')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a premium config reset warning if config was modified' do
|
||||||
|
create(:installation_config, name: 'INSTALLATION_NAME', value: 'custom-name')
|
||||||
|
service.perform
|
||||||
|
expect(Redis::Alfred.get(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING)).to eq('true')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'will not create a premium config reset warning if config is not modified' do
|
||||||
|
create(:installation_config, name: 'INSTALLATION_NAME', value: 'Chatwoot')
|
||||||
|
service.perform
|
||||||
|
expect(Redis::Alfred.get(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# To be enabled in the future when method is uncommented
|
||||||
|
|
||||||
|
# it 'updates the premium configs to default' do
|
||||||
|
# create(:installation_config, name: 'INSTALLATION_NAME', value: 'custom-name')
|
||||||
|
# create(:installation_config, name: 'LOGO', value: '/custom-path/logo.svg')
|
||||||
|
# service.perform
|
||||||
|
# expect(InstallationConfig.find_by(name: 'INSTALLATION_NAME').value).to eq('Chatwoot')
|
||||||
|
# expect(InstallationConfig.find_by(name: 'LOGO').value).to eq('/brand-assets/logo.svg')
|
||||||
|
# end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when pricing plan is not community' do
|
||||||
|
before do
|
||||||
|
allow(ChatwootHub).to receive(:pricing_plan).and_return('enterprise')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unset premium config warning on upgrade' do
|
||||||
|
Redis::Alfred.set(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING, true)
|
||||||
|
service.perform
|
||||||
|
expect(Redis::Alfred.get(Redis::Alfred::CHATWOOT_INSTALLATION_CONFIG_RESET_WARNING)).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not disable the premium features for accounts' do
|
||||||
|
account = create(:account)
|
||||||
|
account.enable_features!('disable_branding', 'audit_logs', 'response_bot')
|
||||||
|
response_bot_account = create(:account)
|
||||||
|
response_bot_account.enable_features!('response_bot')
|
||||||
|
disable_branding_account = create(:account)
|
||||||
|
disable_branding_account.enable_features!('disable_branding')
|
||||||
|
service.perform
|
||||||
|
expect(account.reload.enabled_features.keys).to include('response_bot', 'disable_branding', 'audit_logs')
|
||||||
|
expect(response_bot_account.reload.enabled_features.keys).to include('response_bot')
|
||||||
|
expect(disable_branding_account.reload.enabled_features.keys).to include('disable_branding')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not update the LOGO config' do
|
||||||
|
create(:installation_config, name: 'INSTALLATION_NAME', value: 'custom-name')
|
||||||
|
create(:installation_config, name: 'LOGO', value: '/custom-path/logo.svg')
|
||||||
|
service.perform
|
||||||
|
expect(InstallationConfig.find_by(name: 'INSTALLATION_NAME').value).to eq('custom-name')
|
||||||
|
expect(InstallationConfig.find_by(name: 'LOGO').value).to eq('/custom-path/logo.svg')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -4,7 +4,7 @@ RSpec.describe Internal::CheckNewVersionsJob do
|
|||||||
subject(:job) { described_class.perform_now }
|
subject(:job) { described_class.perform_now }
|
||||||
|
|
||||||
it 'updates the latest chatwoot version in redis' do
|
it 'updates the latest chatwoot version in redis' do
|
||||||
data = { 'version' => '1.2.3' }.to_json
|
data = { 'version' => '1.2.3' }
|
||||||
allow(Rails.env).to receive(:production?).and_return(true)
|
allow(Rails.env).to receive(:production?).and_return(true)
|
||||||
allow(ChatwootHub).to receive(:sync_with_hub).and_return(data)
|
allow(ChatwootHub).to receive(:sync_with_hub).and_return(data)
|
||||||
job
|
job
|
||||||
|
|||||||
Reference in New Issue
Block a user