0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-04 10:39:43 +08:00
discourse/lib/theme_settings_manager/objects.rb
Martin Brennan fc8df41adb
DEV: Add disallowed_groups to theme/component settings (#41792)
Further following on from bee1be8599,
this brings greater parity between theme settings and site settings.

This commit adds a new `disallowed_groups` field to theme and component
settings, which allows theme authors to specify groups that cannot be
selected
by admins for a particular list type or object group type setting.

This is useful for cases where the group-based setting isn't usable
for a group like e.g. anonymous_users, no point allowing them for
a setting that requires a user to be logged in to take effect.

c.f.
https://meta.discourse.org/t/granular-group-based-permissions-for-anonymous-and-logged-in-users/402273/18?u=martin

### List groups

With `disallowed_groups: "4|5"` specified (`logged_in_users` &
`anonymous_users`)

<img width="734" height="450" alt="image"
src="https://github.com/user-attachments/assets/ed8d7338-65fa-44e6-8dce-7073a87076e6"
/>

### Object groups

With `disallowed_groups: "4|5"` specified (`logged_in_users` &
`anonymous_users`)

<img width="696" height="725" alt="image"
src="https://github.com/user-attachments/assets/1a9103d4-cf44-4038-9d62-3838cb779b49"
/>
2026-07-20 09:28:52 +10:00

93 lines
2.5 KiB
Ruby
Vendored

# frozen_string_literal: true
class ThemeSettingsManager::Objects < ThemeSettingsManager
def self.extract_value_from_row(row)
row.json_value
end
def default
hydrate_uploads(@default.map(&:deep_stringify_keys))
end
def value
has_record? ? hydrate_uploads(db_record.json_value) : default
end
def value=(objects)
objects = JSON.parse(objects) if objects.is_a?(::String)
objects = remove_disallowed_groups(objects)
ensure_is_valid_value!(objects)
objects = SchemaSettingsObjectValidator.normalize_uploads(schema:, objects:)
record = has_record? ? update_record!(json_value: objects) : create_record!(json_value: objects)
theme.reload
record.json_value
end
def schema
@opts[:schema]
end
def hydrate_uploads(objects)
SchemaSettingsObjectValidator.hydrate_uploads(schema:, objects:, cdn: true)
end
def remove_disallowed_groups(objects)
return objects if objects.blank?
remove_disallowed_groups_from_objects(objects.deep_dup, schema[:properties])
end
def categories(guardian)
category_ids = Set.new
value.each do |theme_setting_object|
category_ids.merge(
SchemaSettingsObjectValidator.new(
schema:,
object: theme_setting_object,
).property_values_of_type("categories"),
)
end
return [] if category_ids.empty?
Category.secured(guardian).where(id: category_ids)
end
private
def remove_disallowed_groups_from_objects(objects, properties)
objects.each do |object|
properties.each do |property_name, property_attributes|
key = object_key(object, property_name)
next if key.nil?
case property_attributes[:type]
when "groups"
next if property_attributes[:disallowed_groups].blank?
disallowed_ids = property_attributes[:disallowed_groups].to_s.split("|").map(&:to_i)
object[key] = Array(object[key]).reject { |id| disallowed_ids.include?(id) }
when "objects"
nested_objects = object[key]
if nested_objects.is_a?(Array)
remove_disallowed_groups_from_objects(
nested_objects,
property_attributes[:schema][:properties],
)
end
end
end
end
objects
end
def object_key(object, property_name)
string_key = property_name.to_s
return string_key if object.key?(string_key)
symbol_key = property_name.to_sym
symbol_key if object.key?(symbol_key)
end
end