mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
Followup 7e77ce4bd3
We need to automatically resolve group membership into a boolean
for theme object type settings which are of the group type, similar
to what we did in the original commit above for group list type
settings.
This behaves in the same way -- for an object setting schema like this:
```
menu_sections:
type: objects
default:
- name: section 1
groups:
- 1
- 3
schema:
name: menu section
properties:
name:
type: string
groups:
type: groups
resolve_group_membership: true
```
We replace `groups` with a boolean `user_in_groups` (groups is just
the property name, it could be foo_bar etc.) and then you can
do this on the client:
```
for (const section of settings.menu_sections) {
if (section.user_in_groups) {
// User is in at least one selected group for this section.
}
}
```
Rather than inspecting the `currentUser.groups`, which only includes
visible groups, not all groups the user is a member of. This allows
for more accurate permission checks for theme settings that are group
based.
Also c.f.
https://meta.discourse.org/t/granular-group-based-permissions-for-anonymous-and-logged-in-users/402273/18?u=martin
176 lines
4.9 KiB
Ruby
Vendored
176 lines
4.9 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe ThemeSettingsValidator do
|
|
describe ".validate_value" do
|
|
it "does not throw an error when an integer value is given with type `string`" do
|
|
errors = described_class.validate_value(1, ThemeSetting.types[:string], {})
|
|
|
|
expect(errors).to eq([])
|
|
end
|
|
|
|
it "returns the right error messages when value is invalid for type `objects`" do
|
|
errors =
|
|
described_class.validate_value(
|
|
[{ name: "something" }],
|
|
ThemeSetting.types[:objects],
|
|
{
|
|
schema: {
|
|
name: "test",
|
|
properties: {
|
|
name: {
|
|
type: "string",
|
|
validations: {
|
|
max_length: 1,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
expect(errors).to contain_exactly(
|
|
"The property at JSON Pointer '/0/name' must be at most 1 character long.",
|
|
)
|
|
end
|
|
end
|
|
|
|
describe ".validate_resolve_group_membership" do
|
|
it "returns error when resolve_group_membership is true on non-list setting" do
|
|
errors =
|
|
described_class.validate_value(
|
|
"test",
|
|
ThemeSetting.types[:string],
|
|
{ resolve_group_membership: true },
|
|
)
|
|
|
|
expect(errors).to contain_exactly(
|
|
I18n.t("themes.settings_errors.resolve_group_membership_requires_list"),
|
|
)
|
|
end
|
|
|
|
it "returns error when resolve_group_membership is true without list_type group" do
|
|
errors =
|
|
described_class.validate_value(
|
|
"a|b|c",
|
|
ThemeSetting.types[:list],
|
|
{ resolve_group_membership: true, list_type: "compact" },
|
|
)
|
|
|
|
expect(errors).to contain_exactly(
|
|
I18n.t("themes.settings_errors.resolve_group_membership_requires_group_list"),
|
|
)
|
|
end
|
|
|
|
it "returns no errors when resolve_group_membership is true with list_type group" do
|
|
errors =
|
|
described_class.validate_value(
|
|
"1|2|3",
|
|
ThemeSetting.types[:list],
|
|
{ resolve_group_membership: true, list_type: "group" },
|
|
)
|
|
|
|
expect(errors).to eq([])
|
|
end
|
|
|
|
it "returns no errors when resolve_group_membership is false" do
|
|
errors =
|
|
described_class.validate_value(
|
|
"test",
|
|
ThemeSetting.types[:string],
|
|
{ resolve_group_membership: false },
|
|
)
|
|
|
|
expect(errors).to eq([])
|
|
end
|
|
|
|
it "returns no errors when resolve_group_membership is true on an object groups property" do
|
|
errors =
|
|
described_class.validate_value(
|
|
[{ groups: [Group::AUTO_GROUPS[:admins]] }],
|
|
ThemeSetting.types[:objects],
|
|
{
|
|
schema: {
|
|
name: "section",
|
|
properties: {
|
|
groups: {
|
|
type: "groups",
|
|
resolve_group_membership: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
expect(errors).to eq([])
|
|
end
|
|
|
|
it "returns an error when resolve_group_membership is true on a non-groups object property" do
|
|
errors =
|
|
described_class.validate_value(
|
|
[{ name: "section", category_ids: [] }],
|
|
ThemeSetting.types[:objects],
|
|
{
|
|
schema: {
|
|
name: "section",
|
|
properties: {
|
|
name: {
|
|
type: "string",
|
|
resolve_group_membership: true,
|
|
},
|
|
category_ids: {
|
|
type: "categories",
|
|
resolve_group_membership: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
expect(errors).to contain_exactly(
|
|
I18n.t(
|
|
"themes.settings_errors.resolve_group_membership_requires_groups_property",
|
|
property: :name,
|
|
),
|
|
I18n.t(
|
|
"themes.settings_errors.resolve_group_membership_requires_groups_property",
|
|
property: :category_ids,
|
|
),
|
|
)
|
|
end
|
|
|
|
it "returns an error when resolve_group_membership is true on a nested objects property" do
|
|
errors =
|
|
described_class.validate_value(
|
|
[{ links: [] }],
|
|
ThemeSetting.types[:objects],
|
|
{
|
|
schema: {
|
|
name: "section",
|
|
properties: {
|
|
links: {
|
|
type: "objects",
|
|
resolve_group_membership: true,
|
|
schema: {
|
|
name: "link",
|
|
properties: {
|
|
groups: {
|
|
type: "groups",
|
|
resolve_group_membership: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
expect(errors).to contain_exactly(
|
|
I18n.t(
|
|
"themes.settings_errors.resolve_group_membership_requires_groups_property",
|
|
property: :links,
|
|
),
|
|
)
|
|
end
|
|
end
|
|
end
|