mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 08:56:10 +00:00
settings: Add can_set_delete_message_policy_group setting.
Adds new organization setting `can_set_delete_message_policy_group` for defining who can set per-channel message delete permissions. Fixes #34214.
This commit is contained in:
5
api_docs/unmerged.d/ZF-4ce648.md
Normal file
5
api_docs/unmerged.d/ZF-4ce648.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
* `PATCH /realm`, [`POST /register`](/api/register-queue),
|
||||||
|
[`GET /events`](/api/get-events): Added `can_set_delete_message_policy_group`
|
||||||
|
realm setting, which is a [group-setting value](/api/group-setting-values)
|
||||||
|
describing the set of users with permission to change per-channel
|
||||||
|
`can_delete_any_message_group` and `can_delete_own_message_group` settings.
|
||||||
@@ -60,6 +60,7 @@ export const realm_group_setting_name_schema = z.enum([
|
|||||||
"can_move_messages_between_channels_group",
|
"can_move_messages_between_channels_group",
|
||||||
"can_move_messages_between_topics_group",
|
"can_move_messages_between_topics_group",
|
||||||
"can_resolve_topics_group",
|
"can_resolve_topics_group",
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
"can_set_topics_policy_group",
|
"can_set_topics_policy_group",
|
||||||
"can_summarize_topics_group",
|
"can_summarize_topics_group",
|
||||||
"create_multiuse_invite_group",
|
"create_multiuse_invite_group",
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ export function dispatch_normal_event(event) {
|
|||||||
can_move_messages_between_channels_group: noop,
|
can_move_messages_between_channels_group: noop,
|
||||||
can_move_messages_between_topics_group: noop,
|
can_move_messages_between_topics_group: noop,
|
||||||
can_resolve_topics_group: noop,
|
can_resolve_topics_group: noop,
|
||||||
|
can_set_delete_message_policy_group: noop,
|
||||||
can_set_topics_policy_group: noop,
|
can_set_topics_policy_group: noop,
|
||||||
can_summarize_topics_group: noop,
|
can_summarize_topics_group: noop,
|
||||||
create_multiuse_invite_group: noop,
|
create_multiuse_invite_group: noop,
|
||||||
|
|||||||
@@ -856,6 +856,7 @@ export function check_realm_settings_property_changed(elem: HTMLElement): boolea
|
|||||||
case "realm_can_move_messages_between_channels_group":
|
case "realm_can_move_messages_between_channels_group":
|
||||||
case "realm_can_move_messages_between_topics_group":
|
case "realm_can_move_messages_between_topics_group":
|
||||||
case "realm_can_resolve_topics_group":
|
case "realm_can_resolve_topics_group":
|
||||||
|
case "realm_can_set_delete_message_policy_group":
|
||||||
case "realm_can_set_topics_policy_group":
|
case "realm_can_set_topics_policy_group":
|
||||||
case "realm_can_summarize_topics_group":
|
case "realm_can_summarize_topics_group":
|
||||||
case "realm_create_multiuse_invite_group":
|
case "realm_create_multiuse_invite_group":
|
||||||
@@ -1119,6 +1120,7 @@ export function populate_data_for_realm_settings_request(
|
|||||||
"can_move_messages_between_channels_group",
|
"can_move_messages_between_channels_group",
|
||||||
"can_move_messages_between_topics_group",
|
"can_move_messages_between_topics_group",
|
||||||
"can_resolve_topics_group",
|
"can_resolve_topics_group",
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
"can_set_topics_policy_group",
|
"can_set_topics_policy_group",
|
||||||
"can_summarize_topics_group",
|
"can_summarize_topics_group",
|
||||||
"create_multiuse_invite_group",
|
"create_multiuse_invite_group",
|
||||||
@@ -1628,6 +1630,7 @@ export const group_setting_widget_map = new Map<string, GroupSettingPillContaine
|
|||||||
["realm_can_move_messages_between_channels_group", null],
|
["realm_can_move_messages_between_channels_group", null],
|
||||||
["realm_can_move_messages_between_topics_group", null],
|
["realm_can_move_messages_between_topics_group", null],
|
||||||
["realm_can_resolve_topics_group", null],
|
["realm_can_resolve_topics_group", null],
|
||||||
|
["realm_can_set_delete_message_policy_group", null],
|
||||||
["realm_can_set_topics_policy_group", null],
|
["realm_can_set_topics_policy_group", null],
|
||||||
["realm_can_summarize_topics_group", null],
|
["realm_can_summarize_topics_group", null],
|
||||||
["realm_create_multiuse_invite_group", null],
|
["realm_create_multiuse_invite_group", null],
|
||||||
|
|||||||
@@ -754,6 +754,10 @@ export const all_group_setting_labels = {
|
|||||||
can_mention_many_users_group: $t({
|
can_mention_many_users_group: $t({
|
||||||
defaultMessage: "Who can notify a large number of users with a wildcard mention",
|
defaultMessage: "Who can notify a large number of users with a wildcard mention",
|
||||||
}),
|
}),
|
||||||
|
can_set_delete_message_policy_group: $t({
|
||||||
|
defaultMessage:
|
||||||
|
"Who can allow users to delete messages in channels they administer",
|
||||||
|
}),
|
||||||
can_set_topics_policy_group: new Handlebars.SafeString(
|
can_set_topics_policy_group: new Handlebars.SafeString(
|
||||||
$t_html({
|
$t_html({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
@@ -817,6 +821,7 @@ export const realm_group_permission_settings: {
|
|||||||
"can_create_private_channel_group",
|
"can_create_private_channel_group",
|
||||||
"can_add_subscribers_group",
|
"can_add_subscribers_group",
|
||||||
"can_mention_many_users_group",
|
"can_mention_many_users_group",
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
"can_set_topics_policy_group",
|
"can_set_topics_policy_group",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -521,6 +521,7 @@ export function discard_realm_property_element_changes(elem: HTMLElement): void
|
|||||||
case "realm_can_move_messages_between_channels_group":
|
case "realm_can_move_messages_between_channels_group":
|
||||||
case "realm_can_move_messages_between_topics_group":
|
case "realm_can_move_messages_between_topics_group":
|
||||||
case "realm_can_resolve_topics_group":
|
case "realm_can_resolve_topics_group":
|
||||||
|
case "realm_can_set_delete_message_policy_group":
|
||||||
case "realm_can_set_topics_policy_group":
|
case "realm_can_set_topics_policy_group":
|
||||||
case "realm_can_summarize_topics_group":
|
case "realm_can_summarize_topics_group":
|
||||||
case "realm_create_multiuse_invite_group":
|
case "realm_create_multiuse_invite_group":
|
||||||
|
|||||||
@@ -333,6 +333,7 @@ export const realm_schema = z.object({
|
|||||||
realm_can_move_messages_between_channels_group: group_setting_value_schema,
|
realm_can_move_messages_between_channels_group: group_setting_value_schema,
|
||||||
realm_can_move_messages_between_topics_group: group_setting_value_schema,
|
realm_can_move_messages_between_topics_group: group_setting_value_schema,
|
||||||
realm_can_resolve_topics_group: group_setting_value_schema,
|
realm_can_resolve_topics_group: group_setting_value_schema,
|
||||||
|
realm_can_set_delete_message_policy_group: group_setting_value_schema,
|
||||||
realm_can_set_topics_policy_group: group_setting_value_schema,
|
realm_can_set_topics_policy_group: group_setting_value_schema,
|
||||||
realm_can_summarize_topics_group: group_setting_value_schema,
|
realm_can_summarize_topics_group: group_setting_value_schema,
|
||||||
realm_create_multiuse_invite_group: group_setting_value_schema,
|
realm_create_multiuse_invite_group: group_setting_value_schema,
|
||||||
|
|||||||
@@ -549,6 +549,15 @@ export function show_new_stream_modal(): void {
|
|||||||
$("#id_new_topics_policy").prop("disabled", true);
|
$("#id_new_topics_policy").prop("disabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!stream_data.user_can_set_delete_message_policy()) {
|
||||||
|
settings_components.disable_group_permission_setting(
|
||||||
|
$("#id_new_can_delete_any_message_group"),
|
||||||
|
);
|
||||||
|
settings_components.disable_group_permission_setting(
|
||||||
|
$("#id_new_can_delete_own_message_group"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// set default state for "announce stream" and "default stream" option.
|
// set default state for "announce stream" and "default stream" option.
|
||||||
$("#stream_creation_form .default-stream input").prop("checked", false);
|
$("#stream_creation_form .default-stream input").prop("checked", false);
|
||||||
update_announce_stream_state();
|
update_announce_stream_state();
|
||||||
|
|||||||
@@ -635,6 +635,24 @@ export function can_administer_channel(sub: StreamSubscription): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function user_can_set_delete_message_policy(sub?: StreamSubscription): boolean {
|
||||||
|
if (current_user.is_admin) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user_can_set_delete_message_policy = settings_data.user_has_permission_for_group_setting(
|
||||||
|
realm.realm_can_set_delete_message_policy_group,
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
|
"realm",
|
||||||
|
);
|
||||||
|
|
||||||
|
// This handles the case when the stream is being created.
|
||||||
|
if (sub === undefined) {
|
||||||
|
return user_can_set_delete_message_policy;
|
||||||
|
}
|
||||||
|
return user_can_set_delete_message_policy && can_administer_channel(sub);
|
||||||
|
}
|
||||||
|
|
||||||
export function user_can_set_topics_policy(sub?: StreamSubscription): boolean {
|
export function user_can_set_topics_policy(sub?: StreamSubscription): boolean {
|
||||||
if (current_user.is_admin) {
|
if (current_user.is_admin) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -405,6 +405,11 @@ export function enable_or_disable_permission_settings_in_edit_panel(
|
|||||||
if (!stream_data.user_can_set_topics_policy(sub)) {
|
if (!stream_data.user_can_set_topics_policy(sub)) {
|
||||||
$stream_settings.find("#id_topics_policy").prop("disabled", true);
|
$stream_settings.find("#id_topics_policy").prop("disabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!stream_data.user_can_set_delete_message_policy()) {
|
||||||
|
settings_components.disable_group_permission_setting($("#id_can_delete_any_message_group"));
|
||||||
|
settings_components.disable_group_permission_setting($("#id_can_delete_own_message_group"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_announce_stream_option(): void {
|
export function update_announce_stream_option(): void {
|
||||||
|
|||||||
@@ -289,6 +289,10 @@
|
|||||||
<span class="time-unit-text">{{t "{realm_message_content_delete_limit_minutes, plural, one {minute} other {minutes}}"}}</span>
|
<span class="time-unit-text">{{t "{realm_message_content_delete_limit_minutes, plural, one {minute} other {minutes}}"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{> group_setting_value_pill_input
|
||||||
|
setting_name="realm_can_set_delete_message_policy_group"
|
||||||
|
label=group_setting_labels.can_set_delete_message_policy_group}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1799,6 +1799,41 @@ test("user_can_set_topics_policy", ({override}) => {
|
|||||||
assert.equal(stream_data.user_can_set_topics_policy(sub), false);
|
assert.equal(stream_data.user_can_set_topics_policy(sub), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("user_can_set_delete_message_policy", ({override}) => {
|
||||||
|
const sub = {
|
||||||
|
name: "Denmark",
|
||||||
|
subscribed: true,
|
||||||
|
color: "red",
|
||||||
|
stream_id: 1,
|
||||||
|
can_add_subscribers_group: admins_group.id,
|
||||||
|
can_administer_channel_group: nobody_group.id,
|
||||||
|
can_remove_subscribers_group: admins_group.id,
|
||||||
|
};
|
||||||
|
stream_data.add_sub(sub);
|
||||||
|
|
||||||
|
override(realm, "realm_can_set_delete_message_policy_group", nobody_group.id);
|
||||||
|
// Admins can always change per-channel delete_message policy.
|
||||||
|
initialize_and_override_current_user(admin_user_id, override);
|
||||||
|
override(current_user, "is_admin", true);
|
||||||
|
assert.equal(stream_data.user_can_set_delete_message_policy(sub), true);
|
||||||
|
|
||||||
|
initialize_and_override_current_user(moderator_user_id, override);
|
||||||
|
override(current_user, "is_admin", false);
|
||||||
|
assert.equal(stream_data.user_can_set_delete_message_policy(sub), false);
|
||||||
|
|
||||||
|
// Not allowed as user not in can_administer_channel_group.
|
||||||
|
override(realm, "realm_can_set_delete_message_policy_group", everyone_group.id);
|
||||||
|
assert.equal(stream_data.user_can_set_delete_message_policy(sub), false);
|
||||||
|
|
||||||
|
sub.can_administer_channel_group = moderators_group.id;
|
||||||
|
assert.equal(stream_data.user_can_set_delete_message_policy(sub), true);
|
||||||
|
|
||||||
|
// Only realm_can_set_delete_message_policy_group is checked if sub is not provided.
|
||||||
|
assert.equal(stream_data.user_can_set_delete_message_policy(), true);
|
||||||
|
override(realm, "realm_can_set_delete_message_policy_group", nobody_group.id);
|
||||||
|
assert.equal(stream_data.user_can_set_delete_message_policy(sub), false);
|
||||||
|
});
|
||||||
|
|
||||||
test("options for dropdown widget", () => {
|
test("options for dropdown widget", () => {
|
||||||
const denmark = {
|
const denmark = {
|
||||||
subscribed: true,
|
subscribed: true,
|
||||||
|
|||||||
@@ -599,6 +599,7 @@ class GroupSettingUpdateData(GroupSettingUpdateDataCore):
|
|||||||
can_move_messages_between_channels_group: int | UserGroupMembersDict | None = None
|
can_move_messages_between_channels_group: int | UserGroupMembersDict | None = None
|
||||||
can_move_messages_between_topics_group: int | UserGroupMembersDict | None = None
|
can_move_messages_between_topics_group: int | UserGroupMembersDict | None = None
|
||||||
can_resolve_topics_group: int | UserGroupMembersDict | None = None
|
can_resolve_topics_group: int | UserGroupMembersDict | None = None
|
||||||
|
can_set_delete_message_policy_group: int | UserGroupMembersDict | None = None
|
||||||
can_set_topics_policy_group: int | UserGroupMembersDict | None = None
|
can_set_topics_policy_group: int | UserGroupMembersDict | None = None
|
||||||
can_summarize_topics_group: int | UserGroupMembersDict | None = None
|
can_summarize_topics_group: int | UserGroupMembersDict | None = None
|
||||||
direct_message_initiator_group: int | UserGroupMembersDict | None = None
|
direct_message_initiator_group: int | UserGroupMembersDict | None = None
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-06-26 12:52
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0736_alter_stream_can_delete_own_message_group"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="realm",
|
||||||
|
name="can_set_delete_message_policy_group",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.RESTRICT,
|
||||||
|
related_name="+",
|
||||||
|
to="zerver.usergroup",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
from django.db import migrations
|
||||||
|
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import OuterRef
|
||||||
|
|
||||||
|
|
||||||
|
def set_default_value_for_can_set_delete_message_policy_group(
|
||||||
|
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
Realm = apps.get_model("zerver", "Realm")
|
||||||
|
NamedUserGroup = apps.get_model("zerver", "NamedUserGroup")
|
||||||
|
|
||||||
|
MODERATORS_GROUP_NAME = "role:moderators"
|
||||||
|
|
||||||
|
Realm.objects.filter(can_set_delete_message_policy_group=None).update(
|
||||||
|
can_set_delete_message_policy_group=NamedUserGroup.objects.filter(
|
||||||
|
name=MODERATORS_GROUP_NAME, realm=OuterRef("id"), is_system_group=True
|
||||||
|
).values("pk")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
atomic = False
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0737_realm_can_set_delete_message_policy_group"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
set_default_value_for_can_set_delete_message_policy_group,
|
||||||
|
elidable=True,
|
||||||
|
reverse_code=migrations.RunPython.noop,
|
||||||
|
)
|
||||||
|
]
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-06-26 12:55
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0738_set_default_value_for_can_set_delete_message_policy_group"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="realm",
|
||||||
|
name="can_set_delete_message_policy_group",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.RESTRICT,
|
||||||
|
related_name="+",
|
||||||
|
to="zerver.usergroup",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -390,6 +390,11 @@ class Realm(models.Model):
|
|||||||
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# UserGroup which is allowed to set per-channel delete permissions setting.
|
||||||
|
can_set_delete_message_policy_group = models.ForeignKey(
|
||||||
|
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
||||||
|
)
|
||||||
|
|
||||||
# UserGroup which is allowed to set per-channel `topics_policy` setting.
|
# UserGroup which is allowed to set per-channel `topics_policy` setting.
|
||||||
can_set_topics_policy_group = models.ForeignKey(
|
can_set_topics_policy_group = models.ForeignKey(
|
||||||
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
||||||
@@ -836,6 +841,11 @@ class Realm(models.Model):
|
|||||||
allow_everyone_group=True,
|
allow_everyone_group=True,
|
||||||
default_group_name=SystemGroups.EVERYONE,
|
default_group_name=SystemGroups.EVERYONE,
|
||||||
),
|
),
|
||||||
|
can_set_delete_message_policy_group=GroupPermissionSetting(
|
||||||
|
allow_nobody_group=True,
|
||||||
|
allow_everyone_group=False,
|
||||||
|
default_group_name=SystemGroups.MODERATORS,
|
||||||
|
),
|
||||||
can_set_topics_policy_group=GroupPermissionSetting(
|
can_set_topics_policy_group=GroupPermissionSetting(
|
||||||
allow_nobody_group=True,
|
allow_nobody_group=True,
|
||||||
allow_everyone_group=True,
|
allow_everyone_group=True,
|
||||||
|
|||||||
@@ -922,6 +922,9 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
|
|||||||
def can_delete_own_message(self) -> bool:
|
def can_delete_own_message(self) -> bool:
|
||||||
return self.has_permission("can_delete_own_message_group")
|
return self.has_permission("can_delete_own_message_group")
|
||||||
|
|
||||||
|
def can_set_delete_message_policy(self) -> bool:
|
||||||
|
return self.is_realm_admin or self.has_permission("can_set_delete_message_policy_group")
|
||||||
|
|
||||||
def can_set_topics_policy(self) -> bool:
|
def can_set_topics_policy(self) -> bool:
|
||||||
return self.is_realm_admin or self.has_permission("can_set_topics_policy_group")
|
return self.is_realm_admin or self.has_permission("can_set_topics_policy_group")
|
||||||
|
|
||||||
|
|||||||
@@ -4848,6 +4848,20 @@ paths:
|
|||||||
setting controlled this permission; `true` corresponded to `Everyone`, and
|
setting controlled this permission; `true` corresponded to `Everyone`, and
|
||||||
`false` to `Admins`.
|
`false` to `Admins`.
|
||||||
- $ref: "#/components/schemas/GroupSettingValue"
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
|
can_set_delete_message_policy_group:
|
||||||
|
allOf:
|
||||||
|
- description: |
|
||||||
|
A [group-setting value](/api/group-setting-values) defining the set of
|
||||||
|
users who have permission to change per-channel `can_delete_any_message_group`
|
||||||
|
and `can_delete_own_message_group` permission settings. Note that the user
|
||||||
|
must be a member of both this group and the `can_administer_channel_group`
|
||||||
|
of the channel whose message delete settings they want to change.
|
||||||
|
|
||||||
|
Organization administrators can always change these settings of
|
||||||
|
every channel.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 11.0 (feature level ZF-4ce648).
|
||||||
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
can_set_topics_policy_group:
|
can_set_topics_policy_group:
|
||||||
allOf:
|
allOf:
|
||||||
- description: |
|
- description: |
|
||||||
@@ -18312,6 +18326,22 @@ paths:
|
|||||||
setting controlled this permission; `true` corresponded to `Everyone`, and
|
setting controlled this permission; `true` corresponded to `Everyone`, and
|
||||||
`false` to `Admins`.
|
`false` to `Admins`.
|
||||||
- $ref: "#/components/schemas/GroupSettingValue"
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
|
realm_can_set_delete_message_policy_group:
|
||||||
|
allOf:
|
||||||
|
- description: |
|
||||||
|
Present if `realm` is present in `fetch_event_types`.
|
||||||
|
|
||||||
|
A [group-setting value](/api/group-setting-values) defining the set of
|
||||||
|
users who have permission to change per-channel `can_delete_any_message_group`
|
||||||
|
and `can_delete_own_message_group` permission settings. Note that the user
|
||||||
|
must be a member of both this group and the `can_administer_channel_group`
|
||||||
|
of the channel whose message delete settings they want to change.
|
||||||
|
|
||||||
|
Organization administrators can always change these settings of
|
||||||
|
every channel.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 11.0 (feature level ZF-4ce648).
|
||||||
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
realm_can_set_topics_policy_group:
|
realm_can_set_topics_policy_group:
|
||||||
allOf:
|
allOf:
|
||||||
- description: |
|
- description: |
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import orjson
|
import orjson
|
||||||
|
|
||||||
from zerver.actions.channel_folders import check_add_channel_folder
|
from zerver.actions.channel_folders import check_add_channel_folder
|
||||||
from zerver.actions.realm_settings import do_change_realm_plan_type
|
from zerver.actions.realm_settings import (
|
||||||
|
do_change_realm_permission_group_setting,
|
||||||
|
do_change_realm_plan_type,
|
||||||
|
)
|
||||||
from zerver.actions.user_groups import check_add_user_group
|
from zerver.actions.user_groups import check_add_user_group
|
||||||
from zerver.actions.users import do_change_user_role
|
from zerver.actions.users import do_change_user_role
|
||||||
from zerver.lib.default_streams import get_default_stream_ids_for_realm
|
from zerver.lib.default_streams import get_default_stream_ids_for_realm
|
||||||
@@ -563,6 +566,17 @@ class TestCreateStreams(ZulipTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_permission_settings_on_stream_creation(self) -> None:
|
def test_permission_settings_on_stream_creation(self) -> None:
|
||||||
|
realm = get_realm("zulip")
|
||||||
|
members_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.MEMBERS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
do_change_realm_permission_group_setting(
|
||||||
|
realm,
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
|
members_system_group,
|
||||||
|
acting_user=None,
|
||||||
|
)
|
||||||
|
|
||||||
for setting_name in Stream.stream_permission_group_settings:
|
for setting_name in Stream.stream_permission_group_settings:
|
||||||
self.do_test_permission_setting_on_stream_creation(setting_name)
|
self.do_test_permission_setting_on_stream_creation(setting_name)
|
||||||
|
|
||||||
|
|||||||
@@ -1250,6 +1250,13 @@ class ChannelAdministerPermissionTest(ZulipTestCase):
|
|||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
prospero = self.example_user("prospero")
|
prospero = self.example_user("prospero")
|
||||||
|
|
||||||
|
do_change_realm_permission_group_setting(
|
||||||
|
hamlet.realm,
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
|
self.members_group,
|
||||||
|
acting_user=None,
|
||||||
|
)
|
||||||
|
|
||||||
for setting_name in Stream.stream_permission_group_settings:
|
for setting_name in Stream.stream_permission_group_settings:
|
||||||
self.do_test_updating_channel_group_settings(setting_name)
|
self.do_test_updating_channel_group_settings(setting_name)
|
||||||
|
|
||||||
@@ -1333,3 +1340,136 @@ class ChannelAdministerPermissionTest(ZulipTestCase):
|
|||||||
check_channel_topics_policy_update(self.admin)
|
check_channel_topics_policy_update(self.admin)
|
||||||
check_channel_topics_policy_update(self.moderator)
|
check_channel_topics_policy_update(self.moderator)
|
||||||
check_channel_topics_policy_update(hamlet)
|
check_channel_topics_policy_update(hamlet)
|
||||||
|
|
||||||
|
def test_can_set_delete_message_policy_group(self) -> None:
|
||||||
|
user = self.example_user("hamlet")
|
||||||
|
iago = self.example_user("iago")
|
||||||
|
realm = user.realm
|
||||||
|
stream = get_stream("Verona", realm)
|
||||||
|
owners_system_group = NamedUserGroup.objects.get(
|
||||||
|
realm=realm, name=SystemGroups.OWNERS, is_system_group=True
|
||||||
|
)
|
||||||
|
moderators_system_group = NamedUserGroup.objects.get(
|
||||||
|
realm=realm, name=SystemGroups.MODERATORS, is_system_group=True
|
||||||
|
)
|
||||||
|
members_system_group = NamedUserGroup.objects.get(
|
||||||
|
realm=realm, name=SystemGroups.MEMBERS, is_system_group=True
|
||||||
|
)
|
||||||
|
do_change_realm_permission_group_setting(
|
||||||
|
realm,
|
||||||
|
"can_set_delete_message_policy_group",
|
||||||
|
moderators_system_group,
|
||||||
|
acting_user=None,
|
||||||
|
)
|
||||||
|
do_change_stream_group_based_setting(
|
||||||
|
stream, "can_administer_channel_group", members_system_group, acting_user=iago
|
||||||
|
)
|
||||||
|
# Only moderators can change channel-level delete permissions.
|
||||||
|
# Hamlet is not a moderator.
|
||||||
|
subscriptions = [{"name": "new_test_stream"}]
|
||||||
|
result = self.subscribe_via_post(
|
||||||
|
user,
|
||||||
|
subscriptions,
|
||||||
|
subdomain="zulip",
|
||||||
|
extra_post_data={
|
||||||
|
"can_delete_any_message_group": orjson.dumps(owners_system_group.id).decode()
|
||||||
|
},
|
||||||
|
allow_fail=True,
|
||||||
|
)
|
||||||
|
self.assert_json_error(result, "Insufficient permission")
|
||||||
|
|
||||||
|
result = self.subscribe_via_post(
|
||||||
|
user,
|
||||||
|
subscriptions,
|
||||||
|
subdomain="zulip",
|
||||||
|
extra_post_data={
|
||||||
|
"can_delete_own_message_group": orjson.dumps(owners_system_group.id).decode()
|
||||||
|
},
|
||||||
|
allow_fail=True,
|
||||||
|
)
|
||||||
|
self.assert_json_error(result, "Insufficient permission")
|
||||||
|
|
||||||
|
self.login("hamlet")
|
||||||
|
result = self.client_patch(
|
||||||
|
f"/json/streams/{stream.id}",
|
||||||
|
{
|
||||||
|
"can_delete_any_message_group": orjson.dumps(
|
||||||
|
{
|
||||||
|
"new": {
|
||||||
|
"direct_members": [user.id],
|
||||||
|
"direct_subgroups": [
|
||||||
|
owners_system_group.id,
|
||||||
|
moderators_system_group.id,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
|
"can_delete_own_message_group": orjson.dumps(
|
||||||
|
{
|
||||||
|
"new": {
|
||||||
|
"direct_members": [user.id],
|
||||||
|
"direct_subgroups": [
|
||||||
|
owners_system_group.id,
|
||||||
|
moderators_system_group.id,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assert_json_error(result, "Insufficient permission")
|
||||||
|
|
||||||
|
moderator = self.example_user("shiva")
|
||||||
|
|
||||||
|
# Shiva is a moderator.
|
||||||
|
result = self.subscribe_via_post(
|
||||||
|
moderator,
|
||||||
|
subscriptions,
|
||||||
|
subdomain="zulip",
|
||||||
|
extra_post_data={
|
||||||
|
"can_delete_any_message_group": orjson.dumps(owners_system_group.id).decode()
|
||||||
|
},
|
||||||
|
allow_fail=True,
|
||||||
|
)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|
||||||
|
result = self.subscribe_via_post(
|
||||||
|
moderator,
|
||||||
|
subscriptions,
|
||||||
|
subdomain="zulip",
|
||||||
|
extra_post_data={
|
||||||
|
"can_delete_own_message_group": orjson.dumps(owners_system_group.id).decode()
|
||||||
|
},
|
||||||
|
allow_fail=True,
|
||||||
|
)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|
||||||
|
self.login("shiva")
|
||||||
|
result = self.client_patch(
|
||||||
|
f"/json/streams/{stream.id}",
|
||||||
|
{
|
||||||
|
"can_delete_any_message_group": orjson.dumps(
|
||||||
|
{
|
||||||
|
"new": {
|
||||||
|
"direct_members": [user.id],
|
||||||
|
"direct_subgroups": [
|
||||||
|
owners_system_group.id,
|
||||||
|
moderators_system_group.id,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
|
"can_delete_own_message_group": orjson.dumps(
|
||||||
|
{
|
||||||
|
"new": {
|
||||||
|
"direct_members": [user.id],
|
||||||
|
"direct_subgroups": [
|
||||||
|
owners_system_group.id,
|
||||||
|
moderators_system_group.id,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ class HomeTest(ZulipTestCase):
|
|||||||
"realm_can_move_messages_between_channels_group",
|
"realm_can_move_messages_between_channels_group",
|
||||||
"realm_can_move_messages_between_topics_group",
|
"realm_can_move_messages_between_topics_group",
|
||||||
"realm_can_resolve_topics_group",
|
"realm_can_resolve_topics_group",
|
||||||
|
"realm_can_set_delete_message_policy_group",
|
||||||
"realm_can_set_topics_policy_group",
|
"realm_can_set_topics_policy_group",
|
||||||
"realm_can_summarize_topics_group",
|
"realm_can_summarize_topics_group",
|
||||||
"realm_create_multiuse_invite_group",
|
"realm_create_multiuse_invite_group",
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ def update_realm(
|
|||||||
can_move_messages_between_channels_group: Json[GroupSettingChangeRequest] | None = None,
|
can_move_messages_between_channels_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
can_move_messages_between_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
can_move_messages_between_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
can_resolve_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
can_resolve_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
|
can_set_delete_message_policy_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
can_set_topics_policy_group: Json[GroupSettingChangeRequest] | None = None,
|
can_set_topics_policy_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
can_summarize_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
can_summarize_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
create_multiuse_invite_group: Json[GroupSettingChangeRequest] | None = None,
|
create_multiuse_invite_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
|
|||||||
@@ -444,6 +444,11 @@ def update_stream_backend(
|
|||||||
if is_archived is not None and not is_archived:
|
if is_archived is not None and not is_archived:
|
||||||
do_unarchive_stream(stream, stream.name, acting_user=None)
|
do_unarchive_stream(stream, stream.name, acting_user=None)
|
||||||
|
|
||||||
|
if (
|
||||||
|
can_delete_any_message_group is not None or can_delete_own_message_group is not None
|
||||||
|
) and not user_profile.can_set_delete_message_policy():
|
||||||
|
raise JsonableError(_("Insufficient permission"))
|
||||||
|
|
||||||
if description is not None:
|
if description is not None:
|
||||||
do_change_stream_description(stream, description, acting_user=user_profile)
|
do_change_stream_description(stream, description, acting_user=user_profile)
|
||||||
if new_name is not None:
|
if new_name is not None:
|
||||||
@@ -668,6 +673,14 @@ def access_requested_group_permissions(
|
|||||||
setting_name=setting_name,
|
setting_name=setting_name,
|
||||||
permission_configuration=permission_configuration,
|
permission_configuration=permission_configuration,
|
||||||
)
|
)
|
||||||
|
if (
|
||||||
|
setting_name in ["can_delete_any_message_group", "can_delete_own_message_group"]
|
||||||
|
and group_settings_map[setting_name].id
|
||||||
|
!= system_groups_name_dict[SystemGroups.NOBODY].id
|
||||||
|
and not user_profile.can_set_delete_message_policy()
|
||||||
|
):
|
||||||
|
raise JsonableError(_("Insufficient permission"))
|
||||||
|
|
||||||
if not isinstance(setting_value, int):
|
if not isinstance(setting_value, int):
|
||||||
anonymous_group_membership[group_settings_map[setting_name].id] = setting_value
|
anonymous_group_membership[group_settings_map[setting_name].id] = setting_value
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user