mirror of
https://github.com/discourse/discourse.git
synced 2026-08-08 17:53:55 +08:00
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"
/>
179 lines
5 KiB
Ruby
Vendored
179 lines
5 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe ThemeSettingsSerializer do
|
|
fab!(:theme)
|
|
|
|
let(:theme_setting) do
|
|
yaml = File.read("#{Rails.root.join("spec/fixtures/theme_settings/objects_settings.yaml")}")
|
|
theme.set_field(target: :settings, name: "yaml", value: yaml)
|
|
theme.save!
|
|
theme.settings
|
|
end
|
|
|
|
describe "#objects_schema" do
|
|
it "should include the attribute when theme setting is typed objects" do
|
|
payload = ThemeSettingsSerializer.new(theme_setting[:objects_setting]).as_json
|
|
|
|
expect(payload[:theme_settings][:objects_schema][:name]).to eq("section")
|
|
end
|
|
|
|
it "includes disallowed groups metadata for group properties" do
|
|
theme.set_field(target: :settings, name: "yaml", value: <<~YAML)
|
|
objects_setting:
|
|
type: objects
|
|
default: []
|
|
schema:
|
|
name: section
|
|
properties:
|
|
group_ids:
|
|
type: groups
|
|
disallowed_groups: "0|1"
|
|
YAML
|
|
theme.save!
|
|
|
|
payload = ThemeSettingsSerializer.new(theme.reload.settings[:objects_setting]).as_json
|
|
|
|
expect(
|
|
payload[:theme_settings][:objects_schema][:properties][:group_ids][:disallowed_groups],
|
|
).to eq("0|1")
|
|
end
|
|
end
|
|
|
|
describe "#disallowed_groups" do
|
|
it "includes disallowed groups metadata for group list settings" do
|
|
theme.set_field(target: :settings, name: "yaml", value: <<~YAML)
|
|
groups_setting:
|
|
type: list
|
|
list_type: group
|
|
disallowed_groups: "0|1"
|
|
default: "2|3"
|
|
YAML
|
|
theme.save!
|
|
|
|
payload = ThemeSettingsSerializer.new(theme.reload.settings[:groups_setting]).as_json
|
|
|
|
expect(payload[:theme_settings][:disallowed_groups]).to eq("0|1")
|
|
end
|
|
end
|
|
|
|
describe "#valid_values" do
|
|
fab!(:theme_with_enum, :theme)
|
|
|
|
before do
|
|
theme_with_enum.set_field(target: :settings, name: "yaml", value: <<~YAML)
|
|
my_enum:
|
|
type: enum
|
|
default: option_a
|
|
choices:
|
|
- option_a
|
|
- option_b
|
|
- option_c
|
|
YAML
|
|
theme_with_enum.save!
|
|
end
|
|
|
|
it "returns choice labels from locale files when defined" do
|
|
ThemeField.create!(
|
|
theme_id: theme_with_enum.id,
|
|
name: "en",
|
|
type_id: ThemeField.types[:yaml],
|
|
target_id: Theme.targets[:translations],
|
|
value: <<~YAML,
|
|
en:
|
|
theme_metadata:
|
|
settings:
|
|
my_enum:
|
|
choices:
|
|
option_a: "Option A Label"
|
|
option_b: "Option B Label"
|
|
option_c: "Option C Label"
|
|
YAML
|
|
)
|
|
|
|
payload =
|
|
ThemeSettingsSerializer.new(theme_with_enum.reload.settings[:my_enum]).as_json[
|
|
:theme_settings
|
|
]
|
|
|
|
expect(payload[:valid_values]).to eq(
|
|
[
|
|
{ name: "Option A Label", value: "option_a" },
|
|
{ name: "Option B Label", value: "option_b" },
|
|
{ name: "Option C Label", value: "option_c" },
|
|
],
|
|
)
|
|
end
|
|
|
|
it "returns raw values when no locale labels are defined" do
|
|
payload =
|
|
ThemeSettingsSerializer.new(theme_with_enum.settings[:my_enum]).as_json[:theme_settings]
|
|
|
|
expect(payload[:valid_values]).to eq(%w[option_a option_b option_c])
|
|
end
|
|
|
|
it "handles mixed case where some choices have labels and some don't" do
|
|
ThemeField.create!(
|
|
theme_id: theme_with_enum.id,
|
|
name: "en",
|
|
type_id: ThemeField.types[:yaml],
|
|
target_id: Theme.targets[:translations],
|
|
value: <<~YAML,
|
|
en:
|
|
theme_metadata:
|
|
settings:
|
|
my_enum:
|
|
choices:
|
|
option_a: "Option A Label"
|
|
YAML
|
|
)
|
|
|
|
payload =
|
|
ThemeSettingsSerializer.new(theme_with_enum.reload.settings[:my_enum]).as_json[
|
|
:theme_settings
|
|
]
|
|
|
|
expect(payload[:valid_values]).to eq(
|
|
[{ name: "Option A Label", value: "option_a" }, "option_b", "option_c"],
|
|
)
|
|
end
|
|
|
|
it "handles integer choice values with string locale keys" do
|
|
theme_with_enum.set_field(target: :settings, name: "yaml", value: <<~YAML)
|
|
int_enum:
|
|
type: enum
|
|
default: 1
|
|
choices:
|
|
- 1
|
|
- 2
|
|
- 3
|
|
YAML
|
|
theme_with_enum.save!
|
|
|
|
ThemeField.create!(
|
|
theme_id: theme_with_enum.id,
|
|
name: "en",
|
|
type_id: ThemeField.types[:yaml],
|
|
target_id: Theme.targets[:translations],
|
|
value: <<~YAML,
|
|
en:
|
|
theme_metadata:
|
|
settings:
|
|
int_enum:
|
|
choices:
|
|
"1": "One"
|
|
"2": "Two"
|
|
"3": "Three"
|
|
YAML
|
|
)
|
|
|
|
payload =
|
|
ThemeSettingsSerializer.new(theme_with_enum.reload.settings[:int_enum]).as_json[
|
|
:theme_settings
|
|
]
|
|
|
|
expect(payload[:valid_values]).to eq(
|
|
[{ name: "One", value: 1 }, { name: "Two", value: 2 }, { name: "Three", value: 3 }],
|
|
)
|
|
end
|
|
end
|
|
end
|