realm: Add new group setting for who can create private channels.

This commit adds new group based setting to control who can create
private channels.
This commit is contained in:
Sahil Batra 2024-06-17 15:53:43 +05:30 committed by Tim Abbott
parent 428d4284f9
commit 27171d103e
10 changed files with 163 additions and 1 deletions

View File

@ -20,6 +20,13 @@ format used by the Zulip server that they are interacting with.
## Changes in Zulip 9.0 ## Changes in Zulip 9.0
**Feature level 266**
* `PATCH /realm`, [`POST /register`](/api/register-queue),
[`GET /events`](/api/get-events): Added `can_create_private_channel_group`
realm setting, which is a [group-setting value](/api/group-setting-values)
describing the set of users with permission to create private channels.
**Feature level 265** **Feature level 265**
* [`GET /messages`](/api/get-messages), * [`GET /messages`](/api/get-messages),

View File

@ -1048,6 +1048,7 @@ group_setting_update_data_type = DictType(
("create_multiuse_invite_group", int), ("create_multiuse_invite_group", int),
("can_access_all_users_group", int), ("can_access_all_users_group", int),
("can_create_public_channel_group", group_setting_type), ("can_create_public_channel_group", group_setting_type),
("can_create_private_channel_group", group_setting_type),
], ],
) )

View File

@ -0,0 +1,23 @@
# Generated by Django 5.0.6 on 2024-06-17 09:20
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0536_add_message_type"),
]
operations = [
migrations.AddField(
model_name="realm",
name="can_create_private_channel_group",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.RESTRICT,
related_name="+",
to="zerver.usergroup",
),
),
]

View File

@ -0,0 +1,61 @@
# Generated by Django 5.0.6 on 2024-06-17 09:20
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_can_create_private_channel_group_for_existing_realms(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
Realm = apps.get_model("zerver", "Realm")
NamedUserGroup = apps.get_model("zerver", "NamedUserGroup")
MEMBERS_ONLY = 1
ADMINS_ONLY = 2
FULL_MEMBERS_ONLY = 3
MODERATORS_ONLY = 4
Realm.objects.filter(
can_create_private_channel_group=None, create_private_stream_policy=MEMBERS_ONLY
).update(
can_create_private_channel_group=NamedUserGroup.objects.filter(
name="role:members", realm=OuterRef("id"), is_system_group=True
).values("pk")
)
Realm.objects.filter(
can_create_private_channel_group=None, create_private_stream_policy=ADMINS_ONLY
).update(
can_create_private_channel_group=NamedUserGroup.objects.filter(
name="role:administrators", realm=OuterRef("id"), is_system_group=True
).values("pk")
)
Realm.objects.filter(
can_create_private_channel_group=None, create_private_stream_policy=FULL_MEMBERS_ONLY
).update(
can_create_private_channel_group=NamedUserGroup.objects.filter(
name="role:fullmembers", realm=OuterRef("id"), is_system_group=True
).values("pk")
)
Realm.objects.filter(
can_create_private_channel_group=None, create_private_stream_policy=MODERATORS_ONLY
).update(
can_create_private_channel_group=NamedUserGroup.objects.filter(
name="role:moderators", realm=OuterRef("id"), is_system_group=True
).values("pk")
)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0537_realm_can_create_private_channel_group"),
]
operations = [
migrations.RunPython(
set_can_create_private_channel_group_for_existing_realms,
elidable=True,
reverse_code=migrations.RunPython.noop,
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 5.0.6 on 2024-06-17 09:24
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0538_set_can_create_private_channel_group"),
]
operations = [
migrations.AlterField(
model_name="realm",
name="can_create_private_channel_group",
field=models.ForeignKey(
on_delete=django.db.models.deletion.RESTRICT,
related_name="+",
to="zerver.usergroup",
),
),
]

View File

@ -313,6 +313,9 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
can_create_public_channel_group = models.ForeignKey( can_create_public_channel_group = models.ForeignKey(
"UserGroup", on_delete=models.RESTRICT, related_name="+" "UserGroup", on_delete=models.RESTRICT, related_name="+"
) )
can_create_private_channel_group = models.ForeignKey(
"UserGroup", on_delete=models.RESTRICT, related_name="+"
)
# Who in the organization is allowed to delete messages they themselves sent. # Who in the organization is allowed to delete messages they themselves sent.
delete_own_message_policy = models.PositiveSmallIntegerField( delete_own_message_policy = models.PositiveSmallIntegerField(
@ -716,9 +719,19 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
default_group_name=SystemGroups.MEMBERS, default_group_name=SystemGroups.MEMBERS,
id_field_name="can_create_public_channel_group_id", id_field_name="can_create_public_channel_group_id",
), ),
can_create_private_channel_group=GroupPermissionSetting(
require_system_group=False,
allow_internet_group=False,
allow_owners_group=False,
allow_nobody_group=False,
allow_everyone_group=False,
default_group_name=SystemGroups.MEMBERS,
id_field_name="can_create_private_channel_group_id",
),
) )
REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT = [ REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT = [
"can_create_private_channel_group",
"can_create_public_channel_group", "can_create_public_channel_group",
] ]
@ -1081,6 +1094,8 @@ def get_realm_with_settings(realm_id: int) -> Realm:
"can_access_all_users_group__named_user_group", "can_access_all_users_group__named_user_group",
"can_create_public_channel_group", "can_create_public_channel_group",
"can_create_public_channel_group__named_user_group", "can_create_public_channel_group__named_user_group",
"can_create_private_channel_group",
"can_create_private_channel_group__named_user_group",
).get(id=realm_id) ).get(id=realm_id)

View File

@ -4245,6 +4245,20 @@ paths:
**Changes**: New in Zulip 9.0 (feature level 264). Previously **Changes**: New in Zulip 9.0 (feature level 264). Previously
`realm_create_public_stream_policy` field used to control the `realm_create_public_stream_policy` field used to control the
permission to create public channels. permission to create public channels.
can_create_private_channel_group:
allOf:
- $ref: "#/components/schemas/GroupSettingValue"
- description: |
A [group-setting value](/api/group-setting-values) defining
the set of users who have permission to create private
channels in this organization.
This setting cannot be set to `"role:internet"`, `"role:everyone"`,
`"role:owners"` and `"role:nobody"` system groups.
**Changes**: New in Zulip 9.0 (feature level 266). Previously
`realm_create_private_stream_policy` field used to control the
permission to create private channels.
create_private_stream_policy: create_private_stream_policy:
type: integer type: integer
description: | description: |
@ -15250,6 +15264,20 @@ paths:
**Changes**: New in Zulip 9.0 (feature level 264). Previously **Changes**: New in Zulip 9.0 (feature level 264). Previously
`realm_create_public_stream_policy` field used to control the `realm_create_public_stream_policy` field used to control the
permission to create public channels. permission to create public channels.
realm_can_create_private_channel_group:
allOf:
- $ref: "#/components/schemas/GroupSettingValue"
- description: |
A [group-setting value](/api/group-setting-values) defining
the set of users who have permission to create private
channels in this organization.
This setting cannot be set to `"role:internet"`, `"role:everyone"`,
`"role:owners"` and `"role:nobody"` system groups.
**Changes**: New in Zulip 9.0 (feature level 266). Previously
`realm_create_private_stream_policy` field used to control the
permission to create private channels.
realm_create_public_stream_policy: realm_create_public_stream_policy:
type: integer type: integer
deprecated: true deprecated: true

View File

@ -126,6 +126,7 @@ class HomeTest(ZulipTestCase):
"realm_bot_domain", "realm_bot_domain",
"realm_bots", "realm_bots",
"realm_can_access_all_users_group", "realm_can_access_all_users_group",
"realm_can_create_private_channel_group",
"realm_can_create_public_channel_group", "realm_can_create_public_channel_group",
"realm_create_multiuse_invite_group", "realm_create_multiuse_invite_group",
"realm_create_private_stream_policy", "realm_create_private_stream_policy",

View File

@ -1594,7 +1594,7 @@ class RealmAPITest(ZulipTestCase):
realm = get_realm("zulip") realm = get_realm("zulip")
othello = self.example_user("othello") othello = self.example_user("othello")
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
leadership_group = check_add_user_group(realm, "leadership", [hamlet], acting_user=None) leadership_group = NamedUserGroup.objects.get(name="leadership", realm=realm)
moderators_group = NamedUserGroup.objects.get( moderators_group = NamedUserGroup.objects.get(
name=SystemGroups.MODERATORS, realm=realm, is_system_group=True name=SystemGroups.MODERATORS, realm=realm, is_system_group=True
@ -1829,6 +1829,9 @@ class RealmAPITest(ZulipTestCase):
with self.subTest(property=prop): with self.subTest(property=prop):
self.do_test_realm_permission_group_setting_update_api(prop) self.do_test_realm_permission_group_setting_update_api(prop)
check_add_user_group(
get_realm("zulip"), "leadership", [self.example_user("hamlet")], acting_user=None
)
for prop in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT: for prop in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
with self.subTest(property=prop): with self.subTest(property=prop):
self.do_test_realm_permission_group_setting_update_api_with_anonymous_groups(prop) self.do_test_realm_permission_group_setting_update_api_with_anonymous_groups(prop)

View File

@ -148,6 +148,7 @@ def update_realm(
message_content_allowed_in_email_notifications: Optional[Json[bool]] = None, message_content_allowed_in_email_notifications: Optional[Json[bool]] = None,
bot_creation_policy: Optional[Json[BotCreationPolicyEnum]] = None, bot_creation_policy: Optional[Json[BotCreationPolicyEnum]] = None,
can_create_public_channel_group: Optional[Json[GroupSettingChangeRequest]] = None, can_create_public_channel_group: Optional[Json[GroupSettingChangeRequest]] = None,
can_create_private_channel_group: Optional[Json[GroupSettingChangeRequest]] = None,
create_private_stream_policy: Optional[Json[CommonPolicyEnum]] = None, create_private_stream_policy: Optional[Json[CommonPolicyEnum]] = None,
create_web_public_stream_policy: Optional[Json[CreateWebPublicStreamPolicyEnum]] = None, create_web_public_stream_policy: Optional[Json[CreateWebPublicStreamPolicyEnum]] = None,
invite_to_stream_policy: Optional[Json[CommonPolicyEnum]] = None, invite_to_stream_policy: Optional[Json[CommonPolicyEnum]] = None,