discourse/lib/content_security_policy/extension.rb
David Taylor d1474e94a1
FEATURE: Allow themes to specify modifiers in their about.json file (#9097)
There are three modifiers:
- serialize_topic_excerpts (boolean)
- csp_extensions (array of strings)
- svg_icons (array of strings)

When multiple themes are active, the values will be combined. The combination method varies based on the setting. CSP/SVG arrays will be combined. serialize_topic_excerpts will use `Enumerable#any`.
2020-03-11 13:30:45 +00:00

68 lines
1.7 KiB
Ruby

# frozen_string_literal: true
class ContentSecurityPolicy
module Extension
extend self
def site_setting_extension
{ script_src: SiteSetting.content_security_policy_script_src.split('|') }
end
def path_specific_extension(path_info)
{}.tap do |obj|
for_qunit_route = !Rails.env.production? && ["/qunit", "/wizard/qunit"].include?(path_info)
obj[:script_src] = :unsafe_eval if for_qunit_route
end
end
def plugin_extensions
[].tap do |extensions|
Discourse.plugins.each do |plugin|
extensions.concat(plugin.csp_extensions) if plugin.enabled?
end
end
end
THEME_SETTING = 'extend_content_security_policy'
def theme_extensions(theme_ids)
key = "theme_extensions_#{Theme.transform_ids(theme_ids).join(',')}"
cache[key] ||= find_theme_extensions(theme_ids)
end
def clear_theme_extensions_cache!
cache.clear
end
private
def cache
@cache ||= DistributedCache.new('csp_extensions')
end
def find_theme_extensions(theme_ids)
extensions = []
Theme.where(id: Theme.transform_ids(theme_ids)).find_each do |theme|
theme.cached_settings.each do |setting, value|
extensions << build_theme_extension(value.split("|")) if setting.to_s == THEME_SETTING
end
end
extensions << build_theme_extension(ThemeModifierHelper.new(theme_ids: theme_ids).csp_extensions)
extensions
end
def build_theme_extension(entries)
{}.tap do |extension|
entries.each do |entry|
directive, source = entry.split(':', 2).map(&:strip)
extension[directive] ||= []
extension[directive] << source
end
end
end
end
end