mirror of
https://github.com/discourse/discourse.git
synced 2026-08-11 02:59:07 +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"
/>
131 lines
4 KiB
Ruby
Vendored
131 lines
4 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe ThemeSettingsManager::Objects do
|
|
fab!(:theme)
|
|
|
|
let(:theme_setting) do
|
|
yaml = File.read("#{Rails.root.join("spec/fixtures/theme_settings/objects_settings.yaml")}")
|
|
field = theme.set_field(target: :settings, name: "yaml", value: yaml)
|
|
theme.save!
|
|
theme.settings
|
|
end
|
|
|
|
it "can store a list of objects" do
|
|
new_value = [
|
|
{
|
|
"name" => "section 3",
|
|
"links" => [
|
|
{ "name" => "section 3 link 1", "url" => "https://section3link1.com" },
|
|
{ "name" => "section 3 link 2" },
|
|
],
|
|
},
|
|
{
|
|
"name" => "section 4",
|
|
"links" => [{ "name" => "section 4 link 1", "url" => "https://section4link1.com" }],
|
|
},
|
|
]
|
|
|
|
theme_setting[:objects_setting].value = new_value
|
|
|
|
expect(theme.reload.settings[:objects_setting].value).to eq(new_value)
|
|
end
|
|
|
|
it "removes disallowed group ids before saving groups 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: "#{Group::AUTO_GROUPS[:everyone]}|#{Group::AUTO_GROUPS[:admins]}"
|
|
links:
|
|
type: objects
|
|
schema:
|
|
name: link
|
|
properties:
|
|
group_ids:
|
|
type: groups
|
|
disallowed_groups: "#{Group::AUTO_GROUPS[:trust_level_0]}"
|
|
YAML
|
|
theme.save!
|
|
|
|
theme.settings[:objects_setting].value = [
|
|
{
|
|
"group_ids" => [
|
|
Group::AUTO_GROUPS[:everyone],
|
|
Group::AUTO_GROUPS[:admins],
|
|
Group::AUTO_GROUPS[:staff],
|
|
],
|
|
"links" => [
|
|
{
|
|
"group_ids" => [Group::AUTO_GROUPS[:trust_level_0], Group::AUTO_GROUPS[:trust_level_1]],
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
expect(theme.reload.settings[:objects_setting].value).to eq(
|
|
[
|
|
{
|
|
"group_ids" => [Group::AUTO_GROUPS[:staff]],
|
|
"links" => [{ "group_ids" => [Group::AUTO_GROUPS[:trust_level_1]] }],
|
|
},
|
|
],
|
|
)
|
|
end
|
|
|
|
it "raises the right error when there are objects which are not valid" do
|
|
new_value = [
|
|
{ "name" => "section 3", "links" => [{ "url" => "https://some.url.no.name" }] },
|
|
{
|
|
"links" => [
|
|
{
|
|
"name" => "some name that exceeds the max length of 20 characters",
|
|
"url" => "https://some.url",
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
expect { theme_setting[:objects_setting].value = new_value }.to raise_error(
|
|
Discourse::InvalidParameters,
|
|
"The property at JSON Pointer '/0/links/0/name' must be present. The property at JSON Pointer '/1/name' must be present. The property at JSON Pointer '/1/links/0/name' must be at most 20 characters long.",
|
|
)
|
|
end
|
|
|
|
describe "#categories" do
|
|
fab!(:category_1, :category)
|
|
fab!(:category_2, :category)
|
|
fab!(:category_3) { Fabricate(:private_category, group: Fabricate(:group)) }
|
|
fab!(:admin)
|
|
|
|
it "returns an empty array when there are no properties of `categories` type" do
|
|
expect(theme_setting[:objects_setting].categories(Guardian.new)).to eq([])
|
|
end
|
|
|
|
it "returns the categories record for all the properties of `categories` type in a flat array" do
|
|
new_value = [
|
|
{
|
|
"category_ids" => [category_1.id, category_2.id],
|
|
"child_categories" => [{ "category_ids" => [category_3.id] }],
|
|
},
|
|
]
|
|
|
|
theme_setting[:objects_with_categories].value = new_value
|
|
|
|
expect(theme.reload.settings[:objects_with_categories].value).to eq(new_value)
|
|
|
|
expect(theme.settings[:objects_with_categories].categories(Guardian.new)).to contain_exactly(
|
|
category_1,
|
|
category_2,
|
|
)
|
|
|
|
expect(
|
|
theme.settings[:objects_with_categories].categories(Guardian.new(admin)),
|
|
).to contain_exactly(category_1, category_2, category_3)
|
|
end
|
|
end
|
|
end
|