mirror of
https://github.com/discourse/discourse.git
synced 2026-08-04 10:39:43 +08:00
Previously, the duplicate topic title check compared new titles against every topic on the site regardless of visibility: users were blocked by titles in categories they couldn't see or unlisted topics they couldn't find, the bare "Title has already been used" error gave no way to locate the conflict (and doubled as an existence oracle for hidden titles), and the behavior was controlled by two entangled boolean settings. This change scopes the check to the destination category plus whatever the acting user can actually see, links the conflicting topic in the error — safe by construction, since being blocked now implies being able to see it: > This title has already been used by [another topic](). It also consolidates the two booleans into a single `duplicate_topic_titles` enum (`disallowed` / `allowed_across_categories` / `allowed`), with existing values migrated and the old names kept as hidden deprecated aliases that admin search still resolves. Reported in https://meta.discourse.org/t/title-has-already-been-used-in-a-secure-category/123047 Note for self-hosters: env-provided settings can't be migrated — `DISCOURSE_ALLOW_DUPLICATE_TOPIC_TITLES=true` configs need to switch to `DISCOURSE_DUPLICATE_TOPIC_TITLES=allowed`.
60 lines
2.1 KiB
Ruby
Vendored
60 lines
2.1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module SiteSettings
|
|
end
|
|
|
|
module SiteSettings::DeprecatedSettings
|
|
SETTINGS = [
|
|
# [<old setting>, <new_setting>, <override>, <version to drop>]
|
|
["min_first_post_typing_time", "fast_typing_threshold", false, "3.4"],
|
|
["twitter_summary_large_image", "x_summary_large_image", false, "3.4"],
|
|
["external_system_avatars_enabled", "external_system_avatars_url", false, "3.5"],
|
|
["allow_duplicate_topic_titles", "duplicate_topic_titles", false, "2027.1"],
|
|
["allow_duplicate_topic_titles_category", "duplicate_topic_titles", false, "2027.1"],
|
|
]
|
|
|
|
def setup_deprecated_methods
|
|
SETTINGS.each { |s| setup_deprecated_method(*s) }
|
|
end
|
|
|
|
def setup_deprecated_method(old_setting, new_setting, override, version)
|
|
SiteSetting.singleton_class.alias_method(:"_#{old_setting}", :"#{old_setting}") if !override
|
|
|
|
define_singleton_method old_setting do |scoped_to = nil, warn: true|
|
|
if warn
|
|
Discourse.deprecate(
|
|
"`SiteSetting.#{old_setting}` has been deprecated. Please use `SiteSetting.#{new_setting}` instead.",
|
|
drop_from: version,
|
|
)
|
|
end
|
|
|
|
public_send(override ? new_setting : "_#{old_setting}", scoped_to)
|
|
end
|
|
|
|
SiteSetting.singleton_class.alias_method(:"_#{old_setting}?", :"#{old_setting}?") if !override
|
|
|
|
define_singleton_method "#{old_setting}?" do |scoped_to = nil, warn: true|
|
|
if warn
|
|
Discourse.deprecate(
|
|
"`SiteSetting.#{old_setting}?` has been deprecated. Please use `SiteSetting.#{new_setting}?` instead.",
|
|
drop_from: version,
|
|
)
|
|
end
|
|
|
|
public_send("#{override ? new_setting : "_" + old_setting}?", scoped_to)
|
|
end
|
|
|
|
SiteSetting.singleton_class.alias_method(:"_#{old_setting}=", :"#{old_setting}=") if !override
|
|
|
|
define_singleton_method "#{old_setting}=" do |val, warn: true|
|
|
if warn
|
|
Discourse.deprecate(
|
|
"`SiteSetting.#{old_setting}=` has been deprecated. Please use `SiteSetting.#{new_setting}=` instead.",
|
|
drop_from: version,
|
|
)
|
|
end
|
|
|
|
public_send("#{override ? new_setting : "_" + old_setting}=", val)
|
|
end
|
|
end
|
|
end
|