Skip to content

Commit

Permalink
models: Add can_access_all_users_group setting.
Browse files Browse the repository at this point in the history
This commit adds new setting for controlling who can access
all users in the realm which would have "Everyone" and
"Members only" option.

Fixes part of zulip#10970.
  • Loading branch information
sahil839 committed Nov 8, 2023
1 parent 57afb28 commit b85c89d
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 3 deletions.
11 changes: 11 additions & 0 deletions api_docs/changelog.md
Expand Up @@ -20,6 +20,17 @@ format used by the Zulip server that they are interacting with.

## Changes in Zulip 8.0

**Feature level 224**

* `PATCH /realm`, [`POST /register`](/api/register-queue),
[`GET /events`](/api/get-events): Added `can_access_all_users_group_id`
realm setting, which is the ID of the user group whose members can
access all the users in the oragnization.

* [`POST /register`](/api/register-queue): Added `allowed_system_groups`
field to configuration data object of permission settings passed in
`server_supported_permission_settings`.

**Feature level 223**

* `POST /users/me/apns_device_token`:
Expand Down
2 changes: 1 addition & 1 deletion version.py
Expand Up @@ -33,7 +33,7 @@
# Changes should be accompanied by documentation explaining what the
# new level means in api_docs/changelog.md, as well as "**Changes**"
# entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 223
API_FEATURE_LEVEL = 224

# Bump the minor PROVISION_VERSION to indicate that folks should provision
# only when going from an old version of the code to a newer version. Bump
Expand Down
3 changes: 2 additions & 1 deletion zerver/lib/event_schema.py
Expand Up @@ -991,7 +991,8 @@ def check_realm_default_update(
)

group_setting_update_data_type = DictType(
required_keys=[], optional_keys=[("create_multiuse_invite_group", int)]
required_keys=[],
optional_keys=[("create_multiuse_invite_group", int), ("can_access_all_users_group", int)],
)

update_dict_data = UnionType(
Expand Down
3 changes: 2 additions & 1 deletion zerver/lib/types.py
@@ -1,5 +1,5 @@
import datetime
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional, Tuple, TypedDict, TypeVar, Union

from django_stubs_ext import StrPromise
Expand Down Expand Up @@ -291,6 +291,7 @@ class GroupPermissionSetting:
default_group_name: str
id_field_name: str
default_for_system_groups: Optional[str] = None
allowed_system_groups: List[str] = field(default_factory=list)


@dataclass
Expand Down
10 changes: 10 additions & 0 deletions zerver/lib/user_groups.py
Expand Up @@ -215,6 +215,16 @@ def access_user_group_for_setting(
)
)

if (
permission_configuration.allowed_system_groups
and user_group.name not in permission_configuration.allowed_system_groups
):
raise JsonableError(
_("'{setting_name}' setting cannot be set to '{group_name}' group.").format(
setting_name=setting_name, group_name=user_group.name
)
)

return user_group


Expand Down
23 changes: 23 additions & 0 deletions zerver/migrations/0486_realm_can_access_all_users_group.py
@@ -0,0 +1,23 @@
# Generated by Django 4.1.7 on 2023-03-23 14:40

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("zerver", "0485_alter_usermessage_flags_and_add_index"),
]

operations = [
migrations.AddField(
model_name="realm",
name="can_access_all_users_group",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.RESTRICT,
related_name="+",
to="zerver.usergroup",
),
),
]
@@ -0,0 +1,35 @@
# Generated by Django 4.2.5 on 2023-09-21 14:00

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_access_all_users_group(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
Realm = apps.get_model("zerver", "Realm")
UserGroup = apps.get_model("zerver", "UserGroup")

EVERYONE_GROUP_NAME = "role:everyone"

Realm.objects.filter(can_access_all_users_group=None).update(
can_access_all_users_group=UserGroup.objects.filter(
name=EVERYONE_GROUP_NAME, realm=OuterRef("id"), is_system_group=True
).values("pk")
)


class Migration(migrations.Migration):
dependencies = [
("zerver", "0486_realm_can_access_all_users_group"),
]

operations = [
migrations.RunPython(
set_default_value_for_can_access_all_users_group,
elidable=True,
reverse_code=migrations.RunPython.noop,
),
]
22 changes: 22 additions & 0 deletions zerver/migrations/0488_alter_realm_can_access_all_users_group.py
@@ -0,0 +1,22 @@
# Generated by Django 4.2.5 on 2023-09-21 14:07

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("zerver", "0487_set_default_value_for_can_access_all_users_group"),
]

operations = [
migrations.AlterField(
model_name="realm",
name="can_access_all_users_group",
field=models.ForeignKey(
on_delete=django.db.models.deletion.RESTRICT,
related_name="+",
to="zerver.usergroup",
),
),
]
18 changes: 18 additions & 0 deletions zerver/models.py
Expand Up @@ -445,6 +445,14 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
"UserGroup", on_delete=models.RESTRICT, related_name="+"
)

# on_delete field here is set to RESTRICT because we don't want to allow
# deleting a user group in case it is referenced by this setting.
# We are not using PROTECT since we want to allow deletion of user groups
# when realm itself is deleted.
can_access_all_users_group = models.ForeignKey(
"UserGroup", on_delete=models.RESTRICT, related_name="+"
)

# Who in the organization is allowed to invite other users to streams.
invite_to_stream_policy = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY)

Expand Down Expand Up @@ -814,6 +822,16 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
default_group_name=SystemGroups.ADMINISTRATORS,
id_field_name="create_multiuse_invite_group_id",
),
can_access_all_users_group=GroupPermissionSetting(
require_system_group=True,
allow_internet_group=False,
allow_owners_group=False,
allow_nobody_group=False,
allow_everyone_group=True,
default_group_name=SystemGroups.EVERYONE,
id_field_name="can_access_all_users_group_id",
allowed_system_groups=[SystemGroups.EVERYONE],
),
)

DIGEST_WEEKDAY_VALUES = [0, 1, 2, 3, 4, 5, 6]
Expand Down
32 changes: 32 additions & 0 deletions zerver/openapi/zulip.yaml
Expand Up @@ -4527,6 +4527,16 @@ paths:
guest users to prominently highlight their status.

**Changes**: New in Zulip 8.0 (feature level 216).
can_access_all_users_group:
type: integer
description: |
The ID of the [user group](/api/get-user-groups) whose members
are allowed to access all users in the organization.

This setting can currently only be set to `"role:everyone"`
system group.

**Changes**: New in Zulip 8.0 (feature level 224).
additionalProperties: false
example:
{
Expand Down Expand Up @@ -14295,6 +14305,16 @@ paths:
guest users to prominently highlight their status.

**Changes**: New in Zulip 8.0 (feature level 216).
realm_can_access_all_users_group:
type: integer
description: |
The ID of the [user group](/api/get-user-groups) whose members
are allowed to access all users in the organization.

This setting can currently only be set to `"role:members"`
and `"role:everyone"` system groups.

**Changes**: New in Zulip 8.0 (feature level 224).
zulip_plan_is_not_limited:
type: boolean
description: |
Expand Down Expand Up @@ -19361,6 +19381,18 @@ components:
Name of the default group for the setting for system groups.

This is non-null only for group-level settings.
allowed_system_groups:
type: array
description: |
An array of names of system groups to which the setting can
be set to.

If the list is empty, the setting can be set to system groups
based on the other boolean fields.

**Changes**: New in Zulip 8.0 (feature level 224).
items:
type: string
User:
allOf:
- $ref: "#/components/schemas/UserBase"
Expand Down
1 change: 1 addition & 0 deletions zerver/tests/test_home.py
Expand Up @@ -115,6 +115,7 @@ class HomeTest(ZulipTestCase):
"realm_bot_creation_policy",
"realm_bot_domain",
"realm_bots",
"realm_can_access_all_users_group",
"realm_create_multiuse_invite_group",
"realm_create_private_stream_policy",
"realm_create_public_stream_policy",
Expand Down
5 changes: 5 additions & 0 deletions zerver/tests/test_realm.py
Expand Up @@ -1286,6 +1286,11 @@ def do_test_realm_permission_group_setting_update_api(self, setting_name: str) -
user_group.name == SystemGroups.OWNERS
and not setting_permission_configuration.allow_owners_group
)
or (
setting_permission_configuration.allowed_system_groups
and user_group.name
not in setting_permission_configuration.allowed_system_groups
)
):
value = orjson.dumps(user_group.id).decode()

Expand Down
3 changes: 3 additions & 0 deletions zerver/views/realm.py
Expand Up @@ -175,6 +175,9 @@ def update_realm(
default=None,
),
enable_guest_user_indicator: Optional[bool] = REQ(json_validator=check_bool, default=None),
can_access_all_users_group_id: Optional[int] = REQ(
"can_access_all_users_group", json_validator=check_int, default=None
),
) -> HttpResponse:
realm = user_profile.realm

Expand Down

0 comments on commit b85c89d

Please sign in to comment.