From 99de8f4500dfef808fa8def3c8cf2004f9b5a514 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Tue, 20 Sep 2022 06:06:01 +0530 Subject: [PATCH] chore: Improve Helpcenter custom domains (#5456) - Support rendering articles over frontend URL - Support rendering articles over help center URL - Support rendering help center home page in the custom domain root --- .env.example | 2 ++ app/controllers/dashboard_controller.rb | 13 +++++++------ .../public/api/v1/portals/articles_controller.rb | 6 +++--- .../public/api/v1/portals/categories_controller.rb | 6 +++--- app/controllers/public/api/v1/portals_controller.rb | 6 +++--- app/controllers/public_controller.rb | 9 +++++---- app/models/portal.rb | 4 +++- app/views/public/api/v1/portals/show.html.erb | 4 ++-- ...9225556_make_help_center_custom_domain_unique.rb | 5 +++++ db/schema.rb | 3 ++- 10 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 db/migrate/20220919225556_make_help_center_custom_domain_unique.rb diff --git a/.env.example b/.env.example index e802afbff..12262576e 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,8 @@ SECRET_KEY_BASE=replace_with_lengthy_secure_hex # Replace with the URL you are planning to use for your app FRONTEND_URL=http://0.0.0.0:3000 +# To use a dedicated URL for help center pages +# HELPCENTER_URL=http://0.0.0.0:3000 # If the variable is set, all non-authenticated pages would fallback to the default locale. # Whenever a new account is created, the default language will be DEFAULT_LOCALE instead of en diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 61563e42b..49993e6ee 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -4,7 +4,7 @@ class DashboardController < ActionController::Base before_action :set_global_config around_action :switch_locale before_action :ensure_installation_onboarding, only: [:index] - before_action :redirect_to_custom_domain_page + before_action :render_hc_if_custom_domain, only: [:index] layout 'vueapp' @@ -38,13 +38,14 @@ class DashboardController < ActionController::Base redirect_to '/installation/onboarding' if ::Redis::Alfred.get(::Redis::Alfred::CHATWOOT_INSTALLATION_ONBOARDING) end - def redirect_to_custom_domain_page - custom_domain = request.host - portal = Portal.find_by(custom_domain: custom_domain) + def render_hc_if_custom_domain + domain = request.host + return if domain == URI.parse(ENV.fetch('FRONTEND_URL', '')).host - return unless portal + @portal = Portal.find_by(custom_domain: domain) + return unless @portal - redirect_to "/hc/#{portal.slug}" + render 'public/api/v1/portals/show', layout: 'portal', portal: @portal and return end def app_config diff --git a/app/controllers/public/api/v1/portals/articles_controller.rb b/app/controllers/public/api/v1/portals/articles_controller.rb index f2df4add4..0dfa2ea9b 100644 --- a/app/controllers/public/api/v1/portals/articles_controller.rb +++ b/app/controllers/public/api/v1/portals/articles_controller.rb @@ -1,6 +1,6 @@ class Public::Api::V1::Portals::ArticlesController < PublicController before_action :ensure_custom_domain_request, only: [:show, :index] - before_action :set_portal + before_action :portal before_action :set_category before_action :set_article, only: [:show] layout 'portal' @@ -23,8 +23,8 @@ class Public::Api::V1::Portals::ArticlesController < PublicController @category = @portal.categories.find_by!(slug: params[:category_slug]) end - def set_portal - @portal = @portals.find_by!(slug: params[:slug], archived: false) + def portal + @portal ||= Portal.find_by!(slug: params[:slug], archived: false) end def list_params diff --git a/app/controllers/public/api/v1/portals/categories_controller.rb b/app/controllers/public/api/v1/portals/categories_controller.rb index a36be13a1..6a6ba6377 100644 --- a/app/controllers/public/api/v1/portals/categories_controller.rb +++ b/app/controllers/public/api/v1/portals/categories_controller.rb @@ -1,6 +1,6 @@ class Public::Api::V1::Portals::CategoriesController < PublicController before_action :ensure_custom_domain_request, only: [:show, :index] - before_action :set_portal + before_action :portal before_action :set_category, only: [:show] layout 'portal' @@ -16,7 +16,7 @@ class Public::Api::V1::Portals::CategoriesController < PublicController @category = @portal.categories.find_by!(locale: params[:locale], slug: params[:category_slug]) end - def set_portal - @portal = @portals.find_by!(slug: params[:slug], archived: false) + def portal + @portal ||= Portal.find_by!(slug: params[:slug], archived: false) end end diff --git a/app/controllers/public/api/v1/portals_controller.rb b/app/controllers/public/api/v1/portals_controller.rb index 276549eae..c292198a6 100644 --- a/app/controllers/public/api/v1/portals_controller.rb +++ b/app/controllers/public/api/v1/portals_controller.rb @@ -1,13 +1,13 @@ class Public::Api::V1::PortalsController < PublicController before_action :ensure_custom_domain_request, only: [:show] - before_action :set_portal + before_action :portal layout 'portal' def show; end private - def set_portal - @portal = @portals.find_by!(slug: params[:slug], archived: false) + def portal + @portal ||= Portal.find_by!(slug: params[:slug], archived: false) end end diff --git a/app/controllers/public_controller.rb b/app/controllers/public_controller.rb index 25de4b610..0c3f52ff6 100644 --- a/app/controllers/public_controller.rb +++ b/app/controllers/public_controller.rb @@ -7,14 +7,15 @@ class PublicController < ActionController::Base private def ensure_custom_domain_request - custom_domain = request.host + domain = request.host - @portals = ::Portal.where(custom_domain: custom_domain) + return if [URI.parse(ENV.fetch('FRONTEND_URL', '')).host, URI.parse(ENV.fetch('HELPCENTER_URL', '')).host].include?(domain) - return if @portals.present? + @portal = ::Portal.find_by(custom_domain: domain) + return if @portal.present? render json: { - error: "Domain: #{custom_domain} is not registered with us. \ + error: "Domain: #{domain} is not registered with us. \ Please send us an email at support@chatwoot.com with the custom domain name and account API key" }, status: :unauthorized and return end diff --git a/app/models/portal.rb b/app/models/portal.rb index ca7b0b3f0..a52a69253 100644 --- a/app/models/portal.rb +++ b/app/models/portal.rb @@ -18,7 +18,8 @@ # # Indexes # -# index_portals_on_slug (slug) UNIQUE +# index_portals_on_custom_domain (custom_domain) UNIQUE +# index_portals_on_slug (slug) UNIQUE # class Portal < ApplicationRecord include Rails.application.routes.url_helpers @@ -40,6 +41,7 @@ class Portal < ApplicationRecord validates :account_id, presence: true validates :name, presence: true validates :slug, presence: true, uniqueness: true + validates :custom_domain, uniqueness: true, allow_nil: true validate :config_json_format accepts_nested_attributes_for :members diff --git a/app/views/public/api/v1/portals/show.html.erb b/app/views/public/api/v1/portals/show.html.erb index 93f214d4a..ee0275a40 100644 --- a/app/views/public/api/v1/portals/show.html.erb +++ b/app/views/public/api/v1/portals/show.html.erb @@ -1,10 +1,10 @@ -<%= render "hero", portal: @portal %> +<%= render "public/api/v1/portals/hero", portal: @portal %>
<% @portal.categories.each do |category| %> - <%= render "category-block", category: category, portal: @portal %> + <%= render "public/api/v1/portals/category-block", category: category, portal: @portal %> <% end %>
diff --git a/db/migrate/20220919225556_make_help_center_custom_domain_unique.rb b/db/migrate/20220919225556_make_help_center_custom_domain_unique.rb new file mode 100644 index 000000000..89267855c --- /dev/null +++ b/db/migrate/20220919225556_make_help_center_custom_domain_unique.rb @@ -0,0 +1,5 @@ +class MakeHelpCenterCustomDomainUnique < ActiveRecord::Migration[6.1] + def change + add_index :portals, :custom_domain, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 6b41fc443..9b724b99e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_08_09_104508) do +ActiveRecord::Schema.define(version: 2022_09_19_225556) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" @@ -708,6 +708,7 @@ ActiveRecord::Schema.define(version: 2022_08_09_104508) do t.datetime "updated_at", precision: 6, null: false t.jsonb "config", default: {"allowed_locales"=>["en"]} t.boolean "archived", default: false + t.index ["custom_domain"], name: "index_portals_on_custom_domain", unique: true t.index ["slug"], name: "index_portals_on_slug", unique: true end