FEATURE: Create legal topics for set company name (#21620)

Legal topics, such as the Terms of Service and Privacy Policy topics
do not make sense if the entity creating the community is not a company.
These topics will be created and updated only when the company name is
present and deleted when it is not.
This commit is contained in:
Bianca Nenciu 2023-05-24 22:05:36 +02:00 committed by GitHub
parent baa5389a23
commit 61a0ae3755
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 186 additions and 57 deletions

View File

@ -18,12 +18,16 @@
"faq"
}}</LinkTo></li>
{{/if}}
<li class="nav-item-tos"><LinkTo @route="tos">{{i18n
"tos"
}}</LinkTo></li>
<li class="nav-item-privacy"><LinkTo @route="privacy">{{i18n
"privacy"
}}</LinkTo></li>
{{#if (gt this.siteSettings.tos_topic_id 0)}}
<li class="nav-item-tos"><LinkTo @route="tos">{{i18n
"tos"
}}</LinkTo></li>
{{/if}}
{{#if (gt this.siteSettings.privacy_topic_id 0)}}
<li class="nav-item-privacy"><LinkTo @route="privacy">{{i18n
"privacy"
}}</LinkTo></li>
{{/if}}
</ul>
<section class="about description">

View File

@ -10,8 +10,12 @@
<li class='nav-item-faq'><a class='<%= @page == 'faq' ? 'active' : '' %>' href='<%=faq_path%>'><%= t 'js.faq' %></a></li>
<% end %>
<% end %>
<li class='nav-item-tos'><a href='<%= tos_path %>' class='<%= @page == 'tos' ? 'active' : '' %>'><%= t 'js.tos' %></a></li>
<li class='nav-item-privacy'><a href='<%= privacy_path %>' class='<%= @page == 'privacy' ? 'active' : '' %>'><%= t 'js.privacy' %></a></li>
<% if SiteSetting.tos_topic_id > 0 %>
<li class='nav-item-tos'><a href='<%= tos_path %>' class='<%= @page == 'tos' ? 'active' : '' %>'><%= t 'js.tos' %></a></li>
<% end %>
<% if SiteSetting.privacy_topic_id > 0 %>
<li class='nav-item-privacy'><a href='<%= privacy_path %>' class='<%= @page == 'privacy' ? 'active' : '' %>'><%= t 'js.privacy' %></a></li>
<% end %>
</ul>
<% if staff? %>

View File

@ -66,21 +66,23 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value|
Emoji.clear_cache && Discourse.request_refresh! if name == :emoji_deny_list
if (name == :title || name == :site_description) &&
topic = Topic.find_by(id: SiteSetting.welcome_topic_id)
PostRevisor.new(topic.first_post, topic).revise!(
Discourse.system_user,
{
title: I18n.t("discourse_welcome_topic.title", site_title: SiteSetting.title),
raw:
I18n.t(
"discourse_welcome_topic.body",
base_path: Discourse.base_path,
site_title: SiteSetting.title,
site_description: SiteSetting.site_description,
),
},
skip_revision: true,
)
# Update seeded topics
if %i[title site_description].include?(name)
topics = SeedData::Topics.with_default_locale
topics.update(site_setting_names: ["welcome_topic_id"], skip_changed: true)
elsif %i[company_name contact_email governing_law city_for_disputes].include?(name)
topics = SeedData::Topics.with_default_locale
%w[tos_topic_id privacy_topic_id].each do |site_setting|
topic_id = SiteSetting.get(site_setting)
if topic_id > 0 && Topic.with_deleted.exists?(id: topic_id)
if SiteSetting.company_name.blank?
topics.delete(site_setting_names: [site_setting], skip_changed: true)
else
topics.update(site_setting_names: [site_setting], skip_changed: true)
end
elsif SiteSetting.company_name.present?
topics.create(site_setting_names: [site_setting])
end
end
end
end

View File

@ -2477,12 +2477,14 @@ uncategorized:
tos_topic_id:
default: -1
hidden: true
client: true
guidelines_topic_id:
default: -1
hidden: true
privacy_topic_id:
default: -1
hidden: true
client: true
welcome_topic_id:
default: -1
hidden: true

View File

@ -10,18 +10,28 @@ module SeedData
@locale = locale
end
def create(site_setting_names: nil, include_welcome_topics: true)
def create(site_setting_names: nil, include_welcome_topics: true, include_legal_topics: false)
I18n.with_locale(@locale) do
topics(site_setting_names, include_welcome_topics).each { |params| create_topic(**params) }
topics(
site_setting_names: site_setting_names,
include_welcome_topics: include_welcome_topics,
include_legal_topics: include_legal_topics || SiteSetting.company_name.present?,
).each { |params| create_topic(**params) }
end
end
def update(site_setting_names: nil, skip_changed: false)
I18n.with_locale(@locale) do
topics(site_setting_names).each do |params|
params.except!(:category, :after_create)
params[:skip_changed] = skip_changed
update_topic(**params)
topics(site_setting_names: site_setting_names).each do |params|
update_topic(**params.except(:category, :after_create), skip_changed: skip_changed)
end
end
end
def delete(site_setting_names: nil, skip_changed: false)
I18n.with_locale(@locale) do
topics(site_setting_names: site_setting_names).each do |params|
delete_topic(**params.slice(:site_setting_name), skip_changed: skip_changed)
end
end
end
@ -41,12 +51,14 @@ module SeedData
private
def topics(site_setting_names = nil, include_welcome_topics = true)
def topics(site_setting_names: nil, include_welcome_topics: true, include_legal_topics: true)
staff_category = Category.find_by(id: SiteSetting.staff_category_id)
topics = [
# Terms of Service
{
topics = []
# Terms of Service
if include_legal_topics
topics << {
site_setting_name: "tos_topic_id",
title: I18n.t("tos_topic.title"),
raw:
@ -60,24 +72,28 @@ module SeedData
),
category: staff_category,
static_first_reply: true,
},
# FAQ/Guidelines
{
site_setting_name: "guidelines_topic_id",
title: I18n.t("guidelines_topic.title"),
raw: I18n.t("guidelines_topic.body", base_path: Discourse.base_path),
category: staff_category,
static_first_reply: true,
},
# Privacy Policy
{
}
end
# FAQ/Guidelines
topics << {
site_setting_name: "guidelines_topic_id",
title: I18n.t("guidelines_topic.title"),
raw: I18n.t("guidelines_topic.body", base_path: Discourse.base_path),
category: staff_category,
static_first_reply: true,
}
# Privacy Policy
if include_legal_topics
topics << {
site_setting_name: "privacy_topic_id",
title: I18n.t("privacy_topic.title"),
raw: I18n.t("privacy_topic.body"),
category: staff_category,
static_first_reply: true,
},
]
}
end
if include_welcome_topics
# Welcome Topic
@ -152,27 +168,42 @@ module SeedData
end
def update_topic(site_setting_name:, title:, raw:, static_first_reply: false, skip_changed:)
post = find_post(site_setting_name)
post = find_post(site_setting_name, deleted: true)
return if !post
if !skip_changed || unchanged?(post)
changes = { title: title, raw: raw }
post.revise(Discourse.system_user, changes, skip_validations: true)
if post.trashed?
PostDestroyer.new(Discourse.system_user, post).recover
post.reload
end
post.revise(Discourse.system_user, { title: title, raw: raw }, skip_validations: true)
end
if static_first_reply && (reply = first_reply(post)) && (!skip_changed || unchanged?(reply))
changes = { raw: first_reply_raw(title) }
reply.revise(Discourse.system_user, changes, skip_validations: true)
reply.revise(Discourse.system_user, { raw: first_reply_raw(title) }, skip_validations: true)
end
end
def find_post(site_setting_name)
def delete_topic(site_setting_name:, skip_changed:)
post = find_post(site_setting_name)
return if !post
PostDestroyer.new(Discourse.system_user, post).destroy if !skip_changed || unchanged?(post)
end
def find_post(site_setting_name, deleted: false)
topic_id = SiteSetting.get(site_setting_name)
Post.find_by(topic_id: topic_id, post_number: 1) if topic_id > 0
return if topic_id < 1
posts = Post.where(topic_id: topic_id, post_number: 1)
posts = posts.with_deleted if deleted
posts.first
end
def unchanged?(post)
post.last_editor_id == Discourse::SYSTEM_USER_ID
post.last_editor_id == Discourse::SYSTEM_USER_ID &&
(!post.deleted_by_id || post.deleted_by_id == Discourse::SYSTEM_USER_ID)
end
def setting_value(site_setting_key)

View File

@ -17,7 +17,7 @@ desc "ensure the asynchronously-created post_search_data index is present"
task "annotate:ensure_all_indexes" => :environment do |task, args|
# One of the indexes on post_search_data is created by a sidekiq job
# We need to do some acrobatics to create it on-demand
SeedData::Topics.with_default_locale.create(include_welcome_topics: true)
SeedData::Topics.with_default_locale.create
SiteSetting.search_enable_recent_regular_posts_offset_size = 1
Jobs::CreateRecentPostSearchIndexes.new.execute([])
end

View File

@ -43,4 +43,54 @@ RSpec.describe "Setting changes" do
expect(Reviewable.min_score_for_priority(:low)).not_to eq(new_threshold)
end
end
describe "#title and #site_description" do
before do
general_category = Fabricate(:category, name: "General")
SiteSetting.general_category_id = general_category.id
SeedData::Topics.with_default_locale.create(site_setting_names: ["welcome_topic_id"])
end
it "updates the welcome topic when title changes" do
SiteSetting.title = SecureRandom.alphanumeric
topic = Topic.find(SiteSetting.welcome_topic_id)
expect(topic.title).to include(SiteSetting.title)
expect(topic.first_post.raw).to include(SiteSetting.title)
end
it "updates the welcome topic when site_description changes" do
SiteSetting.site_description = SecureRandom.alphanumeric
topic = Topic.find(SiteSetting.welcome_topic_id)
expect(topic.first_post.raw).to include(SiteSetting.site_description)
end
end
describe "#company_name" do
it "creates the TOS and Privacy topics" do
expect { SiteSetting.company_name = "Company Name" }.to change { Topic.count }.by(
2,
).and change { SiteSetting.tos_topic_id }.and change { SiteSetting.privacy_topic_id }
end
it "creates, updates and deletes the topic" do
# Topic is created
expect { SiteSetting.company_name = "Company Name" }.to change { Topic.count }.by(2)
topic = Topic.find(SiteSetting.tos_topic_id)
first_post = topic.first_post
expect(first_post.raw).to include("Company Name")
# Topic is edited
expect { SiteSetting.company_name = "Other Name" }.not_to change { Topic.count }
expect(first_post.reload.raw).to include("Other Name")
# Topic can be deleted
expect { SiteSetting.company_name = "" }.to change { Topic.count }.by(-2)
# Topic can be recovered and edited
SiteSetting.company_name = "New Name"
expect(first_post.reload.raw).to include("New Name")
end
end
end

View File

@ -11,7 +11,7 @@ RSpec.describe SeedData::Topics do
end
def create_topic(name = "welcome_topic_id")
subject.create(site_setting_names: [name])
subject.create(site_setting_names: [name], include_legal_topics: true)
end
describe "#create" do
@ -71,6 +71,19 @@ RSpec.describe SeedData::Topics do
expect { create_topic }.to_not change { Topic.count }
end
it "does not create a legal topic if company_name is not set" do
subject.create(site_setting_names: ["tos_topic_id"])
expect(SiteSetting.tos_topic_id).to eq(-1)
end
it "creates a legal topic if company_name is set" do
SiteSetting.company_name = "Company Name"
subject.create(site_setting_names: ["tos_topic_id"])
expect(SiteSetting.tos_topic_id).to_not eq(-1)
end
end
describe "#update" do
@ -129,6 +142,29 @@ RSpec.describe SeedData::Topics do
end
end
describe "#delete" do
def delete_topic(name = "welcome_topic_id", skip_changed: false)
subject.delete(site_setting_names: [name], skip_changed: skip_changed)
end
it "deletes the topic" do
create_topic
topic = Topic.last
expect { delete_topic }.to change { Topic.count }.by(-1)
end
it "does not delete the topic if changed" do
create_topic
topic = Topic.last
topic.first_post.revise(Fabricate(:admin), raw: "New text of first post.")
expect { delete_topic(skip_changed: true) }.not_to change { Topic.count }
end
end
describe "#reseed_options" do
it "returns only existing topics as options" do
create_topic("guidelines_topic_id")