2023-12-01 14:52:44 +01:00
|
|
|
import json
|
2023-02-28 03:35:01 +01:00
|
|
|
import os
|
2023-12-14 16:44:18 +01:00
|
|
|
import random
|
2018-09-14 13:14:40 +02:00
|
|
|
import re
|
2023-12-14 16:44:18 +01:00
|
|
|
import string
|
2023-11-19 19:45:19 +01:00
|
|
|
from datetime import datetime, timedelta
|
2024-07-12 02:30:23 +02:00
|
|
|
from typing import Any
|
2024-03-13 00:09:01 +01:00
|
|
|
from unittest import mock, skipUnless
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
import orjson
|
2018-10-23 19:25:59 +02:00
|
|
|
from django.conf import settings
|
2023-09-25 22:59:44 +02:00
|
|
|
from django.core import mail
|
2023-12-01 14:52:44 +01:00
|
|
|
from django.test import override_settings
|
2021-04-27 16:56:45 +02:00
|
|
|
from django.utils.timezone import now as timezone_now
|
2023-10-12 19:43:45 +02:00
|
|
|
from typing_extensions import override
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
from confirmation.models import Confirmation, create_confirmation_link
|
2022-04-14 23:58:15 +02:00
|
|
|
from zerver.actions.create_realm import do_change_realm_subdomain, do_create_realm
|
2024-03-13 00:09:01 +01:00
|
|
|
from zerver.actions.create_user import do_create_user
|
2020-05-13 18:09:17 +02:00
|
|
|
from zerver.actions.message_send import (
|
2024-07-04 14:05:48 +02:00
|
|
|
internal_send_group_direct_message,
|
2020-05-13 18:09:17 +02:00
|
|
|
internal_send_private_message,
|
|
|
|
internal_send_stream_message,
|
|
|
|
)
|
2022-04-14 23:57:15 +02:00
|
|
|
from zerver.actions.realm_settings import (
|
2020-10-28 08:44:10 +01:00
|
|
|
do_add_deactivated_redirect,
|
2024-08-22 18:00:14 +02:00
|
|
|
do_change_realm_max_invites,
|
2021-10-07 21:30:54 +02:00
|
|
|
do_change_realm_org_type,
|
2023-11-22 12:33:48 +01:00
|
|
|
do_change_realm_permission_group_setting,
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type,
|
2017-03-18 20:19:44 +01:00
|
|
|
do_deactivate_realm,
|
2023-02-28 04:44:29 +01:00
|
|
|
do_delete_all_realm_attachments,
|
2022-08-03 20:06:59 +02:00
|
|
|
do_reactivate_realm,
|
2018-09-14 13:14:40 +02:00
|
|
|
do_scrub_realm,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
do_send_realm_reactivation_email,
|
2024-02-05 23:52:25 +01:00
|
|
|
do_set_realm_authentication_methods,
|
2020-06-11 00:54:34 +02:00
|
|
|
do_set_realm_property,
|
2021-07-21 13:23:23 +02:00
|
|
|
do_set_realm_user_default_setting,
|
2017-03-18 20:19:44 +01:00
|
|
|
)
|
2022-07-11 08:47:11 +02:00
|
|
|
from zerver.actions.streams import do_deactivate_stream, merge_streams
|
2024-05-23 16:21:25 +02:00
|
|
|
from zerver.actions.user_groups import check_add_user_group
|
2019-05-16 14:48:42 +02:00
|
|
|
from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description
|
2017-07-01 03:56:40 +02:00
|
|
|
from zerver.lib.send_email import send_future_email
|
2020-03-24 14:47:41 +01:00
|
|
|
from zerver.lib.streams import create_stream_if_needed
|
2017-03-08 12:15:16 +01:00
|
|
|
from zerver.lib.test_classes import ZulipTestCase
|
2024-07-16 22:52:01 +02:00
|
|
|
from zerver.lib.test_helpers import activate_push_notification_service
|
2023-02-28 04:44:29 +01:00
|
|
|
from zerver.lib.upload import delete_message_attachments, upload_message_attachment
|
2020-06-11 00:54:34 +02:00
|
|
|
from zerver.models import (
|
|
|
|
Attachment,
|
|
|
|
CustomProfileField,
|
|
|
|
Message,
|
2024-04-18 12:23:46 +02:00
|
|
|
NamedUserGroup,
|
2020-06-11 00:54:34 +02:00
|
|
|
Realm,
|
2020-12-04 10:54:15 +01:00
|
|
|
RealmAuditLog,
|
2022-07-26 15:48:26 +02:00
|
|
|
RealmReactivationStatus,
|
2021-07-21 13:23:23 +02:00
|
|
|
RealmUserDefault,
|
2020-06-11 00:54:34 +02:00
|
|
|
ScheduledEmail,
|
2021-04-27 16:56:45 +02:00
|
|
|
Stream,
|
2021-08-17 09:03:09 +02:00
|
|
|
UserGroupMembership,
|
2020-06-11 00:54:34 +02:00
|
|
|
UserMessage,
|
|
|
|
UserProfile,
|
|
|
|
)
|
2023-12-15 01:55:59 +01:00
|
|
|
from zerver.models.groups import SystemGroups
|
2024-09-03 15:58:19 +02:00
|
|
|
from zerver.models.realm_audit_logs import AuditLogEventType
|
2024-05-22 11:43:10 +02:00
|
|
|
from zerver.models.realms import (
|
|
|
|
CommonPolicyEnum,
|
|
|
|
InviteToRealmPolicyEnum,
|
|
|
|
MoveMessagesBetweenStreamsPolicyEnum,
|
|
|
|
get_realm,
|
|
|
|
)
|
2023-12-15 03:57:04 +01:00
|
|
|
from zerver.models.streams import get_stream
|
2023-12-15 01:16:00 +01:00
|
|
|
from zerver.models.users import get_system_bot, get_user_profile_by_id
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2024-03-13 00:09:01 +01:00
|
|
|
if settings.ZILENCER_ENABLED:
|
|
|
|
from corporate.lib.stripe import get_seat_count
|
|
|
|
|
2017-03-08 12:15:16 +01:00
|
|
|
|
|
|
|
class RealmTest(ZulipTestCase):
|
2021-02-12 08:19:30 +01:00
|
|
|
def assert_user_profile_cache_gets_new_name(
|
|
|
|
self, user_profile: UserProfile, new_realm_name: str
|
|
|
|
) -> None:
|
2017-03-08 12:15:16 +01:00
|
|
|
self.assertEqual(user_profile.realm.name, new_realm_name)
|
|
|
|
|
2020-02-12 16:39:12 +01:00
|
|
|
def test_realm_creation_ensures_internal_realms(self) -> None:
|
2022-04-14 23:58:15 +02:00
|
|
|
with mock.patch("zerver.actions.create_realm.server_initialized", return_value=False):
|
2024-07-12 02:30:32 +02:00
|
|
|
with (
|
|
|
|
mock.patch(
|
|
|
|
"zerver.actions.create_realm.create_internal_realm"
|
|
|
|
) as mock_create_internal,
|
|
|
|
self.assertLogs(level="INFO") as info_logs,
|
|
|
|
):
|
2020-02-12 16:39:12 +01:00
|
|
|
do_create_realm("testrealm", "Test Realm")
|
|
|
|
mock_create_internal.assert_called_once()
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
|
|
|
info_logs.output,
|
2021-02-12 08:20:45 +01:00
|
|
|
["INFO:root:Server not yet initialized. Creating the internal realm first."],
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2020-02-12 16:39:12 +01:00
|
|
|
|
2023-11-20 20:16:03 +01:00
|
|
|
def test_realm_creation_on_special_subdomains_disallowed(self) -> None:
|
2024-07-14 20:30:42 +02:00
|
|
|
with self.settings(SOCIAL_AUTH_SUBDOMAIN="zulipauth"), self.assertRaises(AssertionError):
|
|
|
|
do_create_realm("zulipauth", "Test Realm")
|
2021-08-23 15:14:05 +02:00
|
|
|
|
2024-07-14 20:30:42 +02:00
|
|
|
with (
|
|
|
|
self.settings(SELF_HOSTING_MANAGEMENT_SUBDOMAIN="zulipselfhosting"),
|
|
|
|
self.assertRaises(AssertionError),
|
|
|
|
):
|
|
|
|
do_create_realm("zulipselfhosting", "Test Realm")
|
2023-11-20 20:16:03 +01:00
|
|
|
|
2021-09-14 00:48:21 +02:00
|
|
|
def test_permission_for_education_non_profit_organization(self) -> None:
|
|
|
|
realm = do_create_realm(
|
|
|
|
"test_education_non_profit",
|
|
|
|
"education_org_name",
|
|
|
|
org_type=Realm.ORG_TYPES["education_nonprofit"]["id"],
|
|
|
|
)
|
|
|
|
|
2024-05-31 13:17:00 +02:00
|
|
|
admins_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.can_create_public_channel_group_id, admins_group.id)
|
|
|
|
|
2024-05-22 11:43:10 +02:00
|
|
|
self.assertEqual(realm.invite_to_realm_policy, InviteToRealmPolicyEnum.ADMINS_ONLY)
|
|
|
|
self.assertEqual(
|
|
|
|
realm.move_messages_between_streams_policy,
|
|
|
|
MoveMessagesBetweenStreamsPolicyEnum.MODERATORS_ONLY,
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.invite_to_stream_policy, CommonPolicyEnum.MODERATORS_ONLY)
|
2024-09-17 12:28:33 +02:00
|
|
|
realm = get_realm("test_education_non_profit")
|
|
|
|
moderators_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.MODERATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.can_create_groups.id, moderators_group.id)
|
2021-09-14 00:48:21 +02:00
|
|
|
|
|
|
|
def test_permission_for_education_for_profit_organization(self) -> None:
|
|
|
|
realm = do_create_realm(
|
|
|
|
"test_education_for_profit",
|
|
|
|
"education_org_name",
|
|
|
|
org_type=Realm.ORG_TYPES["education"]["id"],
|
|
|
|
)
|
|
|
|
|
2024-05-31 13:17:00 +02:00
|
|
|
admins_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.can_create_public_channel_group_id, admins_group.id)
|
|
|
|
|
2024-05-22 11:43:10 +02:00
|
|
|
self.assertEqual(realm.invite_to_realm_policy, InviteToRealmPolicyEnum.ADMINS_ONLY)
|
|
|
|
self.assertEqual(
|
|
|
|
realm.move_messages_between_streams_policy,
|
|
|
|
MoveMessagesBetweenStreamsPolicyEnum.MODERATORS_ONLY,
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.invite_to_stream_policy, CommonPolicyEnum.MODERATORS_ONLY)
|
2024-09-17 12:28:33 +02:00
|
|
|
realm = get_realm("test_education_for_profit")
|
|
|
|
moderators_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.MODERATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.can_create_groups.id, moderators_group.id)
|
2021-09-14 00:48:21 +02:00
|
|
|
|
2021-10-06 14:11:48 +02:00
|
|
|
def test_realm_enable_spectator_access(self) -> None:
|
2022-06-02 15:56:30 +02:00
|
|
|
realm = do_create_realm(
|
|
|
|
"test_web_public_true",
|
|
|
|
"Foo",
|
|
|
|
plan_type=Realm.PLAN_TYPE_STANDARD,
|
|
|
|
enable_spectator_access=True,
|
|
|
|
)
|
2021-10-06 14:11:48 +02:00
|
|
|
self.assertEqual(realm.enable_spectator_access, True)
|
|
|
|
|
|
|
|
realm = do_create_realm("test_web_public_false", "Boo", enable_spectator_access=False)
|
|
|
|
self.assertEqual(realm.enable_spectator_access, False)
|
|
|
|
|
2022-06-02 15:56:30 +02:00
|
|
|
with self.assertRaises(AssertionError):
|
|
|
|
realm = do_create_realm("test_web_public_false_1", "Foo", enable_spectator_access=True)
|
|
|
|
|
|
|
|
with self.assertRaises(AssertionError):
|
|
|
|
realm = do_create_realm(
|
|
|
|
"test_web_public_false_2",
|
|
|
|
"Foo",
|
|
|
|
plan_type=Realm.PLAN_TYPE_LIMITED,
|
|
|
|
enable_spectator_access=True,
|
|
|
|
)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_do_set_realm_name_caching(self) -> None:
|
2017-03-08 12:15:16 +01:00
|
|
|
"""The main complicated thing about setting realm names is fighting the
|
|
|
|
cache, and we start by populating the cache for Hamlet, and we end
|
|
|
|
by checking the cache to ensure that the new value is there."""
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
new_name = "Zed You Elle Eye Pea"
|
2021-03-01 11:33:24 +01:00
|
|
|
do_set_realm_property(realm, "name", new_name, acting_user=None)
|
2017-03-08 12:15:16 +01:00
|
|
|
self.assertEqual(get_realm(realm.string_id).name, new_name)
|
2021-02-12 08:20:45 +01:00
|
|
|
self.assert_user_profile_cache_gets_new_name(self.example_user("hamlet"), new_name)
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_update_realm_name_events(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
new_name = "Puliz"
|
2023-04-05 13:36:01 +02:00
|
|
|
with self.capture_send_event_calls(expected_num_events=1) as events:
|
2021-03-01 11:33:24 +01:00
|
|
|
do_set_realm_property(realm, "name", new_name, acting_user=None)
|
2021-02-12 08:20:45 +01:00
|
|
|
event = events[0]["event"]
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
|
|
|
event,
|
|
|
|
dict(
|
2021-02-12 08:20:45 +01:00
|
|
|
type="realm",
|
|
|
|
op="update",
|
|
|
|
property="name",
|
2021-02-12 08:19:30 +01:00
|
|
|
value=new_name,
|
|
|
|
),
|
|
|
|
)
|
2017-03-21 18:08:40 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_update_realm_description_events(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
new_description = "zulip dev group"
|
2023-04-05 13:36:01 +02:00
|
|
|
with self.capture_send_event_calls(expected_num_events=1) as events:
|
2021-03-01 11:33:24 +01:00
|
|
|
do_set_realm_property(realm, "description", new_description, acting_user=None)
|
2021-02-12 08:20:45 +01:00
|
|
|
event = events[0]["event"]
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
|
|
|
event,
|
|
|
|
dict(
|
2021-02-12 08:20:45 +01:00
|
|
|
type="realm",
|
|
|
|
op="update",
|
|
|
|
property="description",
|
2021-02-12 08:19:30 +01:00
|
|
|
value=new_description,
|
|
|
|
),
|
|
|
|
)
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_update_realm_description(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
|
|
|
new_description = "zulip dev group"
|
2021-04-07 22:00:40 +02:00
|
|
|
data = dict(description=new_description)
|
2023-04-05 13:36:01 +02:00
|
|
|
with self.capture_send_event_calls(expected_num_events=1) as events:
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", data)
|
2017-03-20 06:49:13 +01:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2017-03-20 06:49:13 +01:00
|
|
|
self.assertEqual(realm.description, new_description)
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
event = events[0]["event"]
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
|
|
|
event,
|
|
|
|
dict(
|
2021-02-12 08:20:45 +01:00
|
|
|
type="realm",
|
|
|
|
op="update",
|
|
|
|
property="description",
|
2021-02-12 08:19:30 +01:00
|
|
|
value=new_description,
|
|
|
|
),
|
|
|
|
)
|
2017-03-18 20:19:44 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_realm_description_length(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
new_description = "A" * 1001
|
2021-04-07 22:00:40 +02:00
|
|
|
data = dict(description=new_description)
|
2017-03-18 20:19:44 +01:00
|
|
|
|
|
|
|
# create an admin user
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2017-03-18 20:19:44 +01:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", data)
|
2021-04-07 22:00:40 +02:00
|
|
|
self.assert_json_error(result, "description is too long (limit: 1000 characters)")
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2017-03-18 20:19:44 +01:00
|
|
|
self.assertNotEqual(realm.description, new_description)
|
|
|
|
|
2021-09-13 20:01:35 +02:00
|
|
|
def test_realm_convert_demo_realm(self) -> None:
|
|
|
|
data = dict(string_id="coolrealm")
|
|
|
|
|
|
|
|
self.login("iago")
|
|
|
|
result = self.client_patch("/json/realm", data)
|
|
|
|
self.assert_json_error(result, "Must be an organization owner")
|
|
|
|
|
|
|
|
self.login("desdemona")
|
|
|
|
result = self.client_patch("/json/realm", data)
|
|
|
|
self.assert_json_error(result, "Must be a demo organization.")
|
|
|
|
|
|
|
|
data = dict(string_id="lear")
|
|
|
|
self.login("desdemona")
|
|
|
|
realm = get_realm("zulip")
|
2023-11-19 19:45:19 +01:00
|
|
|
realm.demo_organization_scheduled_deletion_date = timezone_now() + timedelta(days=30)
|
2021-09-13 20:01:35 +02:00
|
|
|
realm.save()
|
|
|
|
result = self.client_patch("/json/realm", data)
|
2023-09-25 20:39:58 +02:00
|
|
|
self.assert_json_error(result, "Subdomain already in use. Please choose a different one.")
|
2021-09-13 20:01:35 +02:00
|
|
|
|
|
|
|
# Now try to change the string_id to something available.
|
|
|
|
data = dict(string_id="coolrealm")
|
|
|
|
result = self.client_patch("/json/realm", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
json = orjson.loads(result.content)
|
|
|
|
self.assertEqual(json["realm_uri"], "http://coolrealm.testserver")
|
2024-05-07 06:08:52 +02:00
|
|
|
self.assertEqual(json["realm_url"], "http://coolrealm.testserver")
|
2021-09-13 20:01:35 +02:00
|
|
|
realm = get_realm("coolrealm")
|
|
|
|
self.assertIsNone(realm.demo_organization_scheduled_deletion_date)
|
|
|
|
self.assertEqual(realm.string_id, data["string_id"])
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_realm_name_length(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
new_name = "A" * (Realm.MAX_REALM_NAME_LENGTH + 1)
|
2021-04-07 22:00:40 +02:00
|
|
|
data = dict(name=new_name)
|
2017-08-23 07:03:19 +02:00
|
|
|
|
|
|
|
# create an admin user
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2017-08-23 07:03:19 +02:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", data)
|
2021-04-07 22:00:40 +02:00
|
|
|
self.assert_json_error(result, "name is too long (limit: 40 characters)")
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2017-08-23 07:03:19 +02:00
|
|
|
self.assertNotEqual(realm.name, new_name)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_admin_restrictions_for_changing_realm_name(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
new_name = "Mice will play while the cat is away"
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("othello")
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2021-04-07 22:00:40 +02:00
|
|
|
req = dict(name=new_name)
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "Must be an organization administrator")
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_unauthorized_name_change(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
data = {"full_name": "Sir Hamlet"}
|
|
|
|
user_profile = self.example_user("hamlet")
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login_user(user_profile)
|
2021-03-01 11:33:24 +01:00
|
|
|
do_set_realm_property(user_profile.realm, "name_changes_disabled", True, acting_user=None)
|
2021-02-12 08:20:45 +01:00
|
|
|
url = "/json/settings"
|
2017-07-31 20:44:52 +02:00
|
|
|
result = self.client_patch(url, data)
|
2017-03-13 18:33:49 +01:00
|
|
|
self.assertEqual(result.status_code, 200)
|
|
|
|
# Since the setting fails silently, no message is returned
|
|
|
|
self.assert_in_response("", result)
|
2018-02-02 16:54:26 +01:00
|
|
|
# Realm admins can change their name even setting is disabled.
|
2021-02-12 08:20:45 +01:00
|
|
|
data = {"full_name": "New Iago"}
|
|
|
|
self.login("iago")
|
|
|
|
url = "/json/settings"
|
2018-02-02 16:54:26 +01:00
|
|
|
result = self.client_patch(url, data)
|
2021-07-15 18:31:34 +02:00
|
|
|
self.assert_json_success(result)
|
2017-03-13 18:33:49 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_do_deactivate_realm_clears_user_realm_cache(self) -> None:
|
2017-03-08 12:15:16 +01:00
|
|
|
"""The main complicated thing about deactivating realm names is
|
|
|
|
updating the cache, and we start by populating the cache for
|
|
|
|
Hamlet, and we end by checking the cache to ensure that his
|
|
|
|
realm appears to be deactivated. You can make this test fail
|
|
|
|
by disabling cache.flush_realm()."""
|
2021-03-04 14:31:18 +01:00
|
|
|
hamlet_id = self.example_user("hamlet").id
|
|
|
|
get_user_profile_by_id(hamlet_id)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2021-03-04 14:31:18 +01:00
|
|
|
user = get_user_profile_by_id(hamlet_id)
|
2017-03-08 12:15:16 +01:00
|
|
|
self.assertTrue(user.realm.deactivated)
|
|
|
|
|
2021-08-04 16:47:36 +02:00
|
|
|
def test_do_change_realm_delete_clears_user_realm_cache(self) -> None:
|
|
|
|
hamlet_id = self.example_user("hamlet").id
|
|
|
|
get_user_profile_by_id(hamlet_id)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm.delete()
|
|
|
|
with self.assertRaises(UserProfile.DoesNotExist):
|
|
|
|
get_user_profile_by_id(hamlet_id)
|
|
|
|
|
2018-11-15 23:29:04 +01:00
|
|
|
def test_do_change_realm_subdomain_clears_user_realm_cache(self) -> None:
|
|
|
|
"""The main complicated thing about changing realm subdomains is
|
|
|
|
updating the cache, and we start by populating the cache for
|
|
|
|
Hamlet, and we end by checking the cache to ensure that his
|
|
|
|
realm appears to be deactivated. You can make this test fail
|
|
|
|
by disabling cache.flush_realm()."""
|
2021-03-04 14:31:18 +01:00
|
|
|
hamlet_id = self.example_user("hamlet").id
|
|
|
|
user = get_user_profile_by_id(hamlet_id)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2020-12-06 20:04:33 +01:00
|
|
|
iago = self.example_user("iago")
|
|
|
|
do_change_realm_subdomain(realm, "newzulip", acting_user=iago)
|
2021-03-04 14:31:18 +01:00
|
|
|
user = get_user_profile_by_id(hamlet_id)
|
2018-11-15 23:29:04 +01:00
|
|
|
self.assertEqual(user.realm.string_id, "newzulip")
|
2020-12-18 20:17:20 +01:00
|
|
|
|
|
|
|
placeholder_realm = get_realm("zulip")
|
|
|
|
self.assertTrue(placeholder_realm.deactivated)
|
2024-05-06 15:27:22 +02:00
|
|
|
self.assertEqual(placeholder_realm.deactivated_redirect, user.realm.url)
|
2018-11-15 23:29:04 +01:00
|
|
|
|
2020-12-06 20:04:33 +01:00
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_SUBDOMAIN_CHANGED, acting_user=iago
|
2020-12-06 20:04:33 +01:00
|
|
|
).last()
|
2021-07-24 16:56:39 +02:00
|
|
|
assert realm_audit_log is not None
|
2020-12-06 20:04:33 +01:00
|
|
|
expected_extra_data = {"old_subdomain": "zulip", "new_subdomain": "newzulip"}
|
2023-07-13 19:46:06 +02:00
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
2020-12-06 20:04:33 +01:00
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
user = self.example_user("hamlet")
|
2021-02-12 08:19:30 +01:00
|
|
|
send_future_email(
|
2023-07-18 11:50:12 +02:00
|
|
|
"zerver/emails/onboarding_zulip_topics",
|
2021-02-12 08:19:30 +01:00
|
|
|
user.realm,
|
|
|
|
to_user_ids=[user.id],
|
2023-11-19 19:45:19 +01:00
|
|
|
delay=timedelta(hours=1),
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2017-07-02 21:10:41 +02:00
|
|
|
self.assertEqual(ScheduledEmail.objects.count(), 1)
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
user.realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2017-07-02 21:10:41 +02:00
|
|
|
self.assertEqual(ScheduledEmail.objects.count(), 0)
|
2017-07-01 03:56:40 +02:00
|
|
|
|
2019-05-16 14:48:42 +02:00
|
|
|
def test_do_change_realm_description_clears_cached_descriptions(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2019-05-16 14:48:42 +02:00
|
|
|
rendered_description = get_realm_rendered_description(realm)
|
|
|
|
text_description = get_realm_text_description(realm)
|
|
|
|
|
2021-05-10 07:02:14 +02:00
|
|
|
realm.description = "New description"
|
2021-02-12 08:20:45 +01:00
|
|
|
realm.save(update_fields=["description"])
|
2019-05-16 14:48:42 +02:00
|
|
|
|
|
|
|
new_rendered_description = get_realm_rendered_description(realm)
|
|
|
|
self.assertNotEqual(rendered_description, new_rendered_description)
|
|
|
|
self.assertIn(realm.description, new_rendered_description)
|
|
|
|
|
|
|
|
new_text_description = get_realm_text_description(realm)
|
|
|
|
self.assertNotEqual(text_description, new_text_description)
|
|
|
|
self.assertEqual(realm.description, new_text_description)
|
|
|
|
|
2019-05-08 06:05:18 +02:00
|
|
|
def test_do_deactivate_realm_on_deactivated_realm(self) -> None:
|
2017-05-24 01:26:30 +02:00
|
|
|
"""Ensure early exit is working in realm deactivation"""
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2017-05-24 01:26:30 +02:00
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2017-05-24 01:26:30 +02:00
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2017-05-24 01:26:30 +02:00
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
2020-10-28 08:44:10 +01:00
|
|
|
def test_do_set_deactivated_redirect_on_deactivated_realm(self) -> None:
|
|
|
|
"""Ensure that the redirect url is working when deactivating realm"""
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2020-10-28 08:44:10 +01:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
redirect_url = "new_server.zulip.com"
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2020-10-28 08:44:10 +01:00
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
do_add_deactivated_redirect(realm, redirect_url)
|
|
|
|
self.assertEqual(realm.deactivated_redirect, redirect_url)
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
new_redirect_url = "test.zulip.com"
|
2020-10-28 08:44:10 +01:00
|
|
|
do_add_deactivated_redirect(realm, new_redirect_url)
|
|
|
|
self.assertEqual(realm.deactivated_redirect, new_redirect_url)
|
|
|
|
self.assertNotEqual(realm.deactivated_redirect, redirect_url)
|
|
|
|
|
2022-08-03 20:06:59 +02:00
|
|
|
def test_do_reactivate_realm(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2022-08-03 20:06:59 +02:00
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
|
|
|
do_reactivate_realm(realm)
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
|
|
|
log_entry = RealmAuditLog.objects.last()
|
|
|
|
assert log_entry is not None
|
|
|
|
|
|
|
|
self.assertEqual(log_entry.realm, realm)
|
2024-09-03 15:58:19 +02:00
|
|
|
self.assertEqual(log_entry.event_type, AuditLogEventType.REALM_REACTIVATED)
|
2022-08-03 20:06:59 +02:00
|
|
|
log_entry_id = log_entry.id
|
|
|
|
|
|
|
|
with self.assertLogs(level="WARNING") as m:
|
|
|
|
# do_reactivate_realm on a realm that's not deactivated should be a noop.
|
|
|
|
do_reactivate_realm(realm)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
m.output,
|
|
|
|
[f"WARNING:root:Realm {realm.id} cannot be reactivated because it is already active."],
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
|
|
|
latest_log_entry = RealmAuditLog.objects.last()
|
|
|
|
assert latest_log_entry is not None
|
|
|
|
self.assertEqual(latest_log_entry.id, log_entry_id)
|
|
|
|
|
2018-11-12 14:15:49 +01:00
|
|
|
def test_realm_reactivation_link(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2018-11-12 14:15:49 +01:00
|
|
|
self.assertTrue(realm.deactivated)
|
2022-07-26 15:48:26 +02:00
|
|
|
|
|
|
|
obj = RealmReactivationStatus.objects.create(realm=realm)
|
|
|
|
confirmation_url = create_confirmation_link(obj, Confirmation.REALM_REACTIVATION)
|
2018-11-12 14:15:49 +01:00
|
|
|
response = self.client_get(confirmation_url)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assert_in_success_response(
|
2021-02-12 08:20:45 +01:00
|
|
|
["Your organization has been successfully reactivated"], response
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2018-11-12 14:15:49 +01:00
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2022-07-26 15:48:26 +02:00
|
|
|
# Make sure the link can't be reused.
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2022-07-26 15:48:26 +02:00
|
|
|
response = self.client_get(confirmation_url)
|
|
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
|
2019-09-17 14:04:48 +02:00
|
|
|
def test_realm_reactivation_confirmation_object(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2019-09-17 14:04:48 +02:00
|
|
|
self.assertTrue(realm.deactivated)
|
2022-07-27 22:11:00 +02:00
|
|
|
obj = RealmReactivationStatus.objects.create(realm=realm)
|
|
|
|
create_confirmation_link(obj, Confirmation.REALM_REACTIVATION)
|
2019-09-17 14:04:48 +02:00
|
|
|
confirmation = Confirmation.objects.last()
|
2021-07-24 16:56:39 +02:00
|
|
|
assert confirmation is not None
|
2022-07-27 22:11:00 +02:00
|
|
|
self.assertEqual(confirmation.content_object, obj)
|
2019-09-17 14:04:48 +02:00
|
|
|
self.assertEqual(confirmation.realm, realm)
|
|
|
|
|
2023-09-25 22:59:44 +02:00
|
|
|
def test_do_send_realm_deactivation_email_no_acting_user(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.deactivated, True)
|
|
|
|
self.assert_length(mail.outbox, 1)
|
|
|
|
self.assertIn(
|
|
|
|
"Your Zulip organization Zulip Dev has been deactivated", mail.outbox[0].subject
|
|
|
|
)
|
|
|
|
self.assertIn("Your Zulip organization, Zulip Dev, was deactivated on", mail.outbox[0].body)
|
|
|
|
|
|
|
|
def test_do_send_realm_deactivation_email_by_support(self) -> None:
|
|
|
|
realm = get_realm("lear")
|
|
|
|
king = self.lear_user("king")
|
|
|
|
king.role = UserProfile.ROLE_REALM_OWNER
|
|
|
|
king.save()
|
|
|
|
iago = self.example_user("iago")
|
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=iago, deactivation_reason="owner_request", email_owners=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.deactivated, True)
|
|
|
|
self.assert_length(mail.outbox, 1)
|
|
|
|
self.assertIn(
|
|
|
|
"Your Zulip organization Lear & Co. has been deactivated", mail.outbox[0].subject
|
|
|
|
)
|
|
|
|
self.assertIn(
|
|
|
|
"Your Zulip organization, Lear & Co., was deactivated on",
|
|
|
|
mail.outbox[0].body,
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_do_send_realm_deactivation_email_by_owner(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
iago = self.example_user("iago")
|
|
|
|
iago.role = UserProfile.ROLE_REALM_OWNER
|
|
|
|
iago.save(update_fields=["role"])
|
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=iago, deactivation_reason="owner_request", email_owners=True
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.deactivated, True)
|
|
|
|
self.assert_length(mail.outbox, 2)
|
|
|
|
for email in mail.outbox:
|
|
|
|
if email.to[0] == "iago@zulip.com":
|
|
|
|
self.assertIn(
|
|
|
|
"Your Zulip organization Zulip Dev has been deactivated", email.subject
|
|
|
|
)
|
|
|
|
self.assertIn(
|
|
|
|
"You have deactivated your Zulip organization, Zulip Dev, on", email.body
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.assertIn(
|
|
|
|
"Your Zulip organization Zulip Dev has been deactivated", email.subject
|
|
|
|
)
|
|
|
|
self.assertIn(
|
|
|
|
"Your Zulip organization, Zulip Dev, was deactivated by Iago on", email.body
|
|
|
|
)
|
|
|
|
|
2018-11-12 14:15:49 +01:00
|
|
|
def test_do_send_realm_reactivation_email(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2023-09-25 22:59:44 +02:00
|
|
|
do_deactivate_realm(
|
|
|
|
realm, acting_user=None, deactivation_reason="owner_request", email_owners=False
|
|
|
|
)
|
2022-11-13 22:50:45 +01:00
|
|
|
self.assertEqual(realm.deactivated, True)
|
2020-12-04 11:46:51 +01:00
|
|
|
iago = self.example_user("iago")
|
|
|
|
do_send_realm_reactivation_email(realm, acting_user=iago)
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2023-09-25 22:59:44 +02:00
|
|
|
self.assert_length(mail.outbox, 1)
|
|
|
|
self.assertEqual(self.email_envelope_from(mail.outbox[0]), settings.NOREPLY_EMAIL_ADDRESS)
|
2020-06-05 23:26:35 +02:00
|
|
|
self.assertRegex(
|
2023-09-25 22:59:44 +02:00
|
|
|
self.email_display_from(mail.outbox[0]),
|
2022-12-24 17:31:48 +01:00
|
|
|
rf"^testserver account security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
2020-06-05 23:26:35 +02:00
|
|
|
)
|
2023-09-25 22:59:44 +02:00
|
|
|
self.assertIn("Reactivate your Zulip organization", mail.outbox[0].subject)
|
|
|
|
self.assertIn("Dear former administrators", mail.outbox[0].body)
|
2019-06-20 23:26:54 +02:00
|
|
|
admins = realm.get_human_admin_users()
|
2020-03-12 14:17:25 +01:00
|
|
|
confirmation_url = self.get_confirmation_url_from_outbox(admins[0].delivery_email)
|
2018-11-12 14:15:49 +01:00
|
|
|
response = self.client_get(confirmation_url)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assert_in_success_response(
|
2021-02-12 08:20:45 +01:00
|
|
|
["Your organization has been successfully reactivated"], response
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2018-11-12 14:15:49 +01:00
|
|
|
self.assertFalse(realm.deactivated)
|
2020-12-04 11:46:51 +01:00
|
|
|
self.assertEqual(
|
|
|
|
RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_REACTIVATION_EMAIL_SENT, acting_user=iago
|
2020-12-04 11:46:51 +01:00
|
|
|
).count(),
|
|
|
|
1,
|
|
|
|
)
|
2018-11-12 14:15:49 +01:00
|
|
|
|
|
|
|
def test_realm_reactivation_with_random_link(self) -> None:
|
|
|
|
random_link = "/reactivate/5e89081eb13984e0f3b130bf7a4121d153f1614b"
|
|
|
|
response = self.client_get(random_link)
|
2022-07-26 15:37:43 +02:00
|
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
self.assert_in_response(
|
|
|
|
"The organization reactivation link has expired or is not valid.", response
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2018-11-12 14:15:49 +01:00
|
|
|
|
2024-02-07 12:13:02 +01:00
|
|
|
def test_change_new_stream_announcements_stream(self) -> None:
|
2017-06-09 20:50:38 +02:00
|
|
|
# We need an admin user.
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2017-06-09 20:50:38 +02:00
|
|
|
|
|
|
|
disabled_notif_stream_id = -1
|
2024-02-07 12:13:02 +01:00
|
|
|
req = dict(
|
|
|
|
new_stream_announcements_stream_id=orjson.dumps(disabled_notif_stream_id).decode()
|
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2017-06-09 20:50:38 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-02-07 12:13:02 +01:00
|
|
|
self.assertEqual(realm.new_stream_announcements_stream, None)
|
2017-06-09 20:50:38 +02:00
|
|
|
|
2021-04-27 16:56:45 +02:00
|
|
|
new_notif_stream_id = Stream.objects.get(name="Denmark").id
|
2024-02-07 12:13:02 +01:00
|
|
|
req = dict(new_stream_announcements_stream_id=orjson.dumps(new_notif_stream_id).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2017-06-09 20:50:38 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-02-07 12:13:02 +01:00
|
|
|
assert realm.new_stream_announcements_stream is not None
|
|
|
|
self.assertEqual(realm.new_stream_announcements_stream.id, new_notif_stream_id)
|
2017-06-09 20:50:38 +02:00
|
|
|
|
2023-11-22 18:07:57 +01:00
|
|
|
# Test that admin can set the setting to an unsubscribed private stream as well.
|
|
|
|
new_notif_stream_id = self.make_stream("private_stream", invite_only=True).id
|
2024-02-07 12:13:02 +01:00
|
|
|
req = dict(new_stream_announcements_stream_id=orjson.dumps(new_notif_stream_id).decode())
|
2023-11-22 18:07:57 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
2024-02-07 12:13:02 +01:00
|
|
|
assert realm.new_stream_announcements_stream is not None
|
|
|
|
self.assertEqual(realm.new_stream_announcements_stream.id, new_notif_stream_id)
|
2023-11-22 18:07:57 +01:00
|
|
|
|
2017-06-09 20:50:38 +02:00
|
|
|
invalid_notif_stream_id = 1234
|
2024-02-07 12:13:02 +01:00
|
|
|
req = dict(
|
|
|
|
new_stream_announcements_stream_id=orjson.dumps(invalid_notif_stream_id).decode()
|
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2024-04-16 20:31:49 +02:00
|
|
|
self.assert_json_error(result, "Invalid channel ID")
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-02-07 12:13:02 +01:00
|
|
|
assert realm.new_stream_announcements_stream is not None
|
|
|
|
self.assertNotEqual(realm.new_stream_announcements_stream.id, invalid_notif_stream_id)
|
2017-06-09 20:50:38 +02:00
|
|
|
|
2024-02-07 12:13:02 +01:00
|
|
|
def test_get_default_new_stream_announcements_stream(self) -> None:
|
2017-08-24 00:36:29 +02:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
verona = get_stream("verona", realm)
|
|
|
|
|
2024-02-07 12:13:02 +01:00
|
|
|
new_stream_announcements_stream = realm.get_new_stream_announcements_stream()
|
|
|
|
assert new_stream_announcements_stream is not None
|
|
|
|
self.assertEqual(new_stream_announcements_stream.id, verona.id)
|
|
|
|
do_deactivate_stream(new_stream_announcements_stream, acting_user=None)
|
|
|
|
self.assertIsNone(realm.get_new_stream_announcements_stream())
|
2017-08-24 00:36:29 +02:00
|
|
|
|
2022-07-11 08:47:11 +02:00
|
|
|
def test_merge_streams(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
denmark = get_stream("Denmark", realm)
|
|
|
|
cordelia = self.example_user("cordelia")
|
2024-02-07 12:13:02 +01:00
|
|
|
new_stream_announcements_stream = realm.get_new_stream_announcements_stream()
|
|
|
|
assert new_stream_announcements_stream is not None
|
2024-05-09 18:59:39 +02:00
|
|
|
new_stream_announcements_stream_messages_count = Message.objects.filter(
|
|
|
|
realm_id=realm.id, recipient=new_stream_announcements_stream.recipient
|
|
|
|
).count()
|
2022-07-11 08:47:11 +02:00
|
|
|
|
|
|
|
create_stream_if_needed(realm, "Atlantis")
|
|
|
|
self.subscribe(cordelia, "Atlantis")
|
|
|
|
self.send_stream_message(cordelia, "Atlantis")
|
|
|
|
atlantis = get_stream("Atlantis", realm)
|
|
|
|
|
|
|
|
stats = merge_streams(realm, denmark, denmark)
|
|
|
|
self.assertEqual(stats, (0, 0, 0))
|
|
|
|
|
|
|
|
stats = merge_streams(realm, denmark, atlantis)
|
|
|
|
self.assertEqual(stats, (1, 1, 1))
|
|
|
|
|
|
|
|
with self.assertRaises(Stream.DoesNotExist):
|
|
|
|
get_stream("Atlantis", realm)
|
|
|
|
|
2024-02-07 12:13:02 +01:00
|
|
|
stats = merge_streams(realm, denmark, new_stream_announcements_stream)
|
2024-05-09 18:59:39 +02:00
|
|
|
self.assertEqual(stats, (2, new_stream_announcements_stream_messages_count, 10))
|
2024-02-07 12:13:02 +01:00
|
|
|
self.assertIsNone(realm.get_new_stream_announcements_stream())
|
2022-07-11 08:47:11 +02:00
|
|
|
|
2024-02-07 17:11:43 +01:00
|
|
|
def test_change_signup_announcements_stream(self) -> None:
|
2017-10-20 16:55:04 +02:00
|
|
|
# We need an admin user.
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2017-10-20 16:55:04 +02:00
|
|
|
|
2024-02-07 17:11:43 +01:00
|
|
|
disabled_signup_announcements_stream_id = -1
|
2021-02-12 08:19:30 +01:00
|
|
|
req = dict(
|
2024-02-07 17:11:43 +01:00
|
|
|
signup_announcements_stream_id=orjson.dumps(
|
|
|
|
disabled_signup_announcements_stream_id
|
2021-02-12 08:19:30 +01:00
|
|
|
).decode()
|
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2017-10-20 16:55:04 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-02-07 17:11:43 +01:00
|
|
|
self.assertEqual(realm.signup_announcements_stream, None)
|
2017-10-20 16:55:04 +02:00
|
|
|
|
2024-02-07 17:11:43 +01:00
|
|
|
new_signup_announcements_stream_id = Stream.objects.get(name="Denmark").id
|
2021-02-12 08:19:30 +01:00
|
|
|
req = dict(
|
2024-02-07 17:11:43 +01:00
|
|
|
signup_announcements_stream_id=orjson.dumps(new_signup_announcements_stream_id).decode()
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2017-12-20 17:58:49 +01:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2017-10-20 16:55:04 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-02-07 17:11:43 +01:00
|
|
|
assert realm.signup_announcements_stream is not None
|
|
|
|
self.assertEqual(realm.signup_announcements_stream.id, new_signup_announcements_stream_id)
|
2017-10-20 16:55:04 +02:00
|
|
|
|
2023-11-22 18:07:57 +01:00
|
|
|
# Test that admin can set the setting to an unsubscribed private stream as well.
|
2024-02-07 17:11:43 +01:00
|
|
|
new_signup_announcements_stream_id = self.make_stream("private_stream", invite_only=True).id
|
2023-11-22 18:07:57 +01:00
|
|
|
req = dict(
|
2024-02-07 17:11:43 +01:00
|
|
|
signup_announcements_stream_id=orjson.dumps(new_signup_announcements_stream_id).decode()
|
2023-11-22 18:07:57 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
2024-02-07 17:11:43 +01:00
|
|
|
assert realm.signup_announcements_stream is not None
|
|
|
|
self.assertEqual(realm.signup_announcements_stream.id, new_signup_announcements_stream_id)
|
2023-11-22 18:07:57 +01:00
|
|
|
|
2024-02-07 17:11:43 +01:00
|
|
|
invalid_signup_announcements_stream_id = 1234
|
2021-02-12 08:19:30 +01:00
|
|
|
req = dict(
|
2024-02-07 17:11:43 +01:00
|
|
|
signup_announcements_stream_id=orjson.dumps(
|
|
|
|
invalid_signup_announcements_stream_id
|
2021-02-12 08:19:30 +01:00
|
|
|
).decode()
|
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2024-04-16 20:31:49 +02:00
|
|
|
self.assert_json_error(result, "Invalid channel ID")
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-02-07 17:11:43 +01:00
|
|
|
assert realm.signup_announcements_stream is not None
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertNotEqual(
|
2024-02-07 17:11:43 +01:00
|
|
|
realm.signup_announcements_stream.id, invalid_signup_announcements_stream_id
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2017-10-20 16:55:04 +02:00
|
|
|
|
2024-02-07 17:11:43 +01:00
|
|
|
def test_get_default_signup_announcements_stream(self) -> None:
|
2017-10-04 02:01:22 +02:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
verona = get_stream("verona", realm)
|
2024-02-07 17:11:43 +01:00
|
|
|
realm.signup_announcements_stream = verona
|
|
|
|
realm.save(update_fields=["signup_announcements_stream"])
|
2017-10-04 02:01:22 +02:00
|
|
|
|
2024-02-07 17:11:43 +01:00
|
|
|
signup_announcements_stream = realm.get_signup_announcements_stream()
|
|
|
|
assert signup_announcements_stream is not None
|
|
|
|
self.assertEqual(signup_announcements_stream, verona)
|
|
|
|
do_deactivate_stream(signup_announcements_stream, acting_user=None)
|
|
|
|
self.assertIsNone(realm.get_signup_announcements_stream())
|
2017-10-04 02:01:22 +02:00
|
|
|
|
2024-01-26 14:45:37 +01:00
|
|
|
def test_change_zulip_update_announcements_stream(self) -> None:
|
|
|
|
# We need an admin user.
|
|
|
|
self.login("iago")
|
|
|
|
|
|
|
|
disabled_zulip_update_announcements_stream_id = -1
|
|
|
|
req = dict(
|
|
|
|
zulip_update_announcements_stream_id=orjson.dumps(
|
|
|
|
disabled_zulip_update_announcements_stream_id
|
|
|
|
).decode()
|
|
|
|
)
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.zulip_update_announcements_stream, None)
|
|
|
|
|
|
|
|
new_zulip_update_announcements_stream_id = Stream.objects.get(name="Denmark").id
|
|
|
|
req = dict(
|
|
|
|
zulip_update_announcements_stream_id=orjson.dumps(
|
|
|
|
new_zulip_update_announcements_stream_id
|
|
|
|
).decode()
|
|
|
|
)
|
|
|
|
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
assert realm.zulip_update_announcements_stream is not None
|
|
|
|
self.assertEqual(
|
|
|
|
realm.zulip_update_announcements_stream.id, new_zulip_update_announcements_stream_id
|
|
|
|
)
|
|
|
|
|
|
|
|
# Test that admin can set the setting to an unsubscribed private stream as well.
|
|
|
|
new_zulip_update_announcements_stream_id = self.make_stream(
|
|
|
|
"private_stream", invite_only=True
|
|
|
|
).id
|
|
|
|
req = dict(
|
|
|
|
zulip_update_announcements_stream_id=orjson.dumps(
|
|
|
|
new_zulip_update_announcements_stream_id
|
|
|
|
).decode()
|
|
|
|
)
|
|
|
|
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
assert realm.zulip_update_announcements_stream is not None
|
|
|
|
self.assertEqual(
|
|
|
|
realm.zulip_update_announcements_stream.id, new_zulip_update_announcements_stream_id
|
|
|
|
)
|
|
|
|
|
|
|
|
invalid_zulip_update_announcements_stream_id = 1234
|
|
|
|
req = dict(
|
|
|
|
zulip_update_announcements_stream_id=orjson.dumps(
|
|
|
|
invalid_zulip_update_announcements_stream_id
|
|
|
|
).decode()
|
|
|
|
)
|
|
|
|
result = self.client_patch("/json/realm", req)
|
2024-04-16 20:31:49 +02:00
|
|
|
self.assert_json_error(result, "Invalid channel ID")
|
2024-01-26 14:45:37 +01:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
assert realm.zulip_update_announcements_stream is not None
|
|
|
|
self.assertNotEqual(
|
|
|
|
realm.zulip_update_announcements_stream.id, invalid_zulip_update_announcements_stream_id
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_get_default_zulip_update_announcements_stream(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
verona = get_stream("verona", realm)
|
|
|
|
realm.zulip_update_announcements_stream = verona
|
|
|
|
realm.save(update_fields=["zulip_update_announcements_stream"])
|
|
|
|
|
|
|
|
zulip_update_announcements_stream = realm.get_zulip_update_announcements_stream()
|
|
|
|
assert zulip_update_announcements_stream is not None
|
|
|
|
self.assertEqual(zulip_update_announcements_stream, verona)
|
|
|
|
do_deactivate_stream(zulip_update_announcements_stream, acting_user=None)
|
|
|
|
self.assertIsNone(realm.get_zulip_update_announcements_stream())
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_change_realm_default_language(self) -> None:
|
2017-03-08 12:15:16 +01:00
|
|
|
# we need an admin user.
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2017-03-08 12:15:16 +01:00
|
|
|
# Test to make sure that when invalid languages are passed
|
|
|
|
# as the default realm language, correct validation error is
|
|
|
|
# raised and the invalid language is not saved in db
|
|
|
|
invalid_lang = "invalid_lang"
|
2021-04-07 22:00:40 +02:00
|
|
|
req = dict(default_language=invalid_lang)
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-06-10 06:41:04 +02:00
|
|
|
self.assert_json_error(result, f"Invalid language '{invalid_lang}'")
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2017-03-08 12:15:16 +01:00
|
|
|
self.assertNotEqual(realm.default_language, invalid_lang)
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2020-06-11 00:26:49 +02:00
|
|
|
def test_deactivate_realm_by_owner(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("desdemona")
|
|
|
|
realm = get_realm("zulip")
|
2018-01-30 14:58:50 +01:00
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_post("/json/realm/deactivate")
|
2018-01-30 14:58:50 +01:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2018-01-30 14:58:50 +01:00
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
2020-06-11 00:26:49 +02:00
|
|
|
def test_deactivate_realm_by_non_owner(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
|
|
|
realm = get_realm("zulip")
|
2018-01-30 14:58:50 +01:00
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_post("/json/realm/deactivate")
|
2020-06-11 00:26:49 +02:00
|
|
|
self.assert_json_error(result, "Must be an organization owner")
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2018-01-30 14:58:50 +01:00
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2019-11-16 19:16:34 +01:00
|
|
|
def test_invalid_integer_attribute_values(self) -> None:
|
2024-09-09 20:02:22 +02:00
|
|
|
integer_values = [
|
|
|
|
key for key, value in Realm.property_types.items() if value in (int, (int, type(None)))
|
|
|
|
]
|
2019-11-16 19:16:34 +01:00
|
|
|
|
|
|
|
invalid_values = dict(
|
|
|
|
bot_creation_policy=10,
|
|
|
|
invite_to_stream_policy=10,
|
|
|
|
message_retention_days=10,
|
2020-04-27 22:41:31 +02:00
|
|
|
video_chat_provider=10,
|
2021-03-31 13:10:46 +02:00
|
|
|
giphy_rating=10,
|
2019-11-16 19:16:34 +01:00
|
|
|
waiting_period_threshold=-10,
|
|
|
|
digest_weekday=10,
|
2020-07-12 21:26:45 +02:00
|
|
|
message_content_delete_limit_seconds=-10,
|
2020-09-04 18:53:22 +02:00
|
|
|
wildcard_mention_policy=10,
|
2021-04-02 18:47:08 +02:00
|
|
|
invite_to_realm_policy=10,
|
2021-04-08 19:24:01 +02:00
|
|
|
move_messages_between_streams_policy=10,
|
2022-09-22 10:53:37 +02:00
|
|
|
edit_topic_policy=10,
|
|
|
|
message_content_edit_limit_seconds=0,
|
2023-01-26 12:53:27 +01:00
|
|
|
move_messages_within_stream_limit_seconds=0,
|
2022-10-11 13:19:49 +02:00
|
|
|
move_messages_between_streams_limit_seconds=0,
|
2019-11-16 19:16:34 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
# We need an admin user.
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2019-11-16 19:16:34 +01:00
|
|
|
|
|
|
|
for name in integer_values:
|
|
|
|
invalid_value = invalid_values.get(name)
|
|
|
|
if invalid_value is None:
|
2021-02-12 08:20:45 +01:00
|
|
|
raise AssertionError(f"No test created for {name}")
|
2019-11-16 19:16:34 +01:00
|
|
|
|
|
|
|
self.do_test_invalid_integer_attribute_value(name, invalid_value)
|
|
|
|
|
|
|
|
def do_test_invalid_integer_attribute_value(self, val_name: str, invalid_val: int) -> None:
|
|
|
|
possible_messages = {
|
2020-06-14 02:57:50 +02:00
|
|
|
f"Invalid {val_name}",
|
|
|
|
f"Bad value for '{val_name}'",
|
|
|
|
f"Bad value for '{val_name}': {invalid_val}",
|
|
|
|
f"Invalid {val_name} {invalid_val}",
|
2024-05-17 19:44:28 +02:00
|
|
|
f"{val_name} is too small",
|
2024-09-09 20:02:22 +02:00
|
|
|
"Must be an organization owner",
|
2019-11-16 19:16:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
req = {val_name: invalid_val}
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2019-11-16 19:16:34 +01:00
|
|
|
msg = self.get_json_error(result)
|
|
|
|
self.assertTrue(msg in possible_messages)
|
|
|
|
|
2018-04-23 14:51:30 +02:00
|
|
|
def test_change_video_chat_provider(self) -> None:
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
2021-02-12 08:20:45 +01:00
|
|
|
get_realm("zulip").video_chat_provider, Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"]
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
2018-04-23 14:51:30 +02:00
|
|
|
|
2020-04-27 22:41:31 +02:00
|
|
|
invalid_video_chat_provider_value = 10
|
2020-08-07 01:09:47 +02:00
|
|
|
req = {"video_chat_provider": orjson.dumps(invalid_video_chat_provider_value).decode()}
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assert_json_error(
|
2023-01-18 03:23:15 +01:00
|
|
|
result, f"Invalid video_chat_provider {invalid_video_chat_provider_value}"
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2019-05-10 10:32:47 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
req = {
|
|
|
|
"video_chat_provider": orjson.dumps(
|
2021-02-12 08:20:45 +01:00
|
|
|
Realm.VIDEO_CHAT_PROVIDERS["disabled"]["id"]
|
2021-02-12 08:19:30 +01:00
|
|
|
).decode()
|
|
|
|
}
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-04-08 00:23:15 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
2021-02-12 08:20:45 +01:00
|
|
|
get_realm("zulip").video_chat_provider, Realm.VIDEO_CHAT_PROVIDERS["disabled"]["id"]
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2020-04-08 00:23:15 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
req = {
|
|
|
|
"video_chat_provider": orjson.dumps(
|
2021-02-12 08:20:45 +01:00
|
|
|
Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"]
|
2021-02-12 08:19:30 +01:00
|
|
|
).decode()
|
|
|
|
}
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2018-04-23 14:51:30 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
2021-02-12 08:20:45 +01:00
|
|
|
get_realm("zulip").video_chat_provider, Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"]
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
req = {
|
|
|
|
"video_chat_provider": orjson.dumps(
|
2021-02-12 08:20:45 +01:00
|
|
|
Realm.VIDEO_CHAT_PROVIDERS["big_blue_button"]["id"]
|
2021-02-12 08:19:30 +01:00
|
|
|
).decode()
|
|
|
|
}
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-04-27 22:41:31 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
2021-02-12 08:20:45 +01:00
|
|
|
get_realm("zulip").video_chat_provider,
|
|
|
|
Realm.VIDEO_CHAT_PROVIDERS["big_blue_button"]["id"],
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2020-04-27 22:41:31 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
req = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"video_chat_provider": orjson.dumps(Realm.VIDEO_CHAT_PROVIDERS["zoom"]["id"]).decode()
|
2021-02-12 08:19:30 +01:00
|
|
|
}
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2019-11-16 09:26:28 +01:00
|
|
|
self.assert_json_success(result)
|
2018-12-28 20:45:54 +01:00
|
|
|
|
2018-08-09 21:38:22 +02:00
|
|
|
def test_initial_plan_type(self) -> None:
|
|
|
|
with self.settings(BILLING_ENABLED=True):
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(do_create_realm("hosted", "hosted").plan_type, Realm.PLAN_TYPE_LIMITED)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
|
|
|
get_realm("hosted").max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
get_realm("hosted").message_visibility_limit, Realm.MESSAGE_VISIBILITY_LIMITED
|
|
|
|
)
|
2019-01-14 11:22:59 +01:00
|
|
|
self.assertEqual(get_realm("hosted").upload_quota_gb, Realm.UPLOAD_QUOTA_LIMITED)
|
2018-10-17 10:50:59 +02:00
|
|
|
|
2018-08-09 21:38:22 +02:00
|
|
|
with self.settings(BILLING_ENABLED=False):
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(
|
|
|
|
do_create_realm("onpremise", "onpremise").plan_type, Realm.PLAN_TYPE_SELF_HOSTED
|
|
|
|
)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assertEqual(
|
2021-02-12 08:20:45 +01:00
|
|
|
get_realm("onpremise").max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
self.assertEqual(get_realm("onpremise").message_visibility_limit, None)
|
2019-01-14 11:22:59 +01:00
|
|
|
self.assertEqual(get_realm("onpremise").upload_quota_gb, None)
|
2018-08-09 21:38:22 +02:00
|
|
|
|
2024-02-05 23:52:25 +01:00
|
|
|
def test_initial_auth_methods(self) -> None:
|
|
|
|
with self.settings(
|
|
|
|
BILLING_ENABLED=True,
|
|
|
|
DEVELOPMENT=False,
|
|
|
|
AUTHENTICATION_BACKENDS=(
|
|
|
|
"zproject.backends.EmailAuthBackend",
|
|
|
|
"zproject.backends.AzureADAuthBackend",
|
|
|
|
"zproject.backends.SAMLAuthBackend",
|
|
|
|
),
|
|
|
|
):
|
|
|
|
# Test a Cloud-like realm creation.
|
|
|
|
# Only the auth backends available on the free plan should be enabled.
|
|
|
|
realm = do_create_realm("hosted", "hosted")
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
realm.authentication_methods_dict(),
|
|
|
|
{
|
|
|
|
"Email": True,
|
|
|
|
"AzureAD": False,
|
|
|
|
"SAML": False,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
# Now make sure that a self-hosted server creates realms with all auth methods enabled.
|
|
|
|
with self.settings(BILLING_ENABLED=False):
|
|
|
|
realm = do_create_realm("onpremise", "onpremise")
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
realm.authentication_methods_dict(),
|
|
|
|
{
|
|
|
|
"Email": True,
|
|
|
|
"AzureAD": True,
|
|
|
|
"SAML": True,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2021-10-07 21:30:54 +02:00
|
|
|
def test_change_org_type(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
iago = self.example_user("iago")
|
|
|
|
self.assertEqual(realm.org_type, Realm.ORG_TYPES["business"]["id"])
|
|
|
|
|
|
|
|
do_change_realm_org_type(realm, Realm.ORG_TYPES["government"]["id"], acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 16:46:18 +02:00
|
|
|
event_type=AuditLogEventType.REALM_ORG_TYPE_CHANGED
|
2021-10-07 21:30:54 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": Realm.ORG_TYPES["business"]["id"],
|
|
|
|
"new_value": Realm.ORG_TYPES["government"]["id"],
|
|
|
|
}
|
2023-07-13 19:46:06 +02:00
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
2021-10-07 21:30:54 +02:00
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.org_type, Realm.ORG_TYPES["government"]["id"])
|
|
|
|
|
2024-08-22 18:00:14 +02:00
|
|
|
def test_change_realm_max_invites(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
iago = self.example_user("iago")
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
|
|
|
self.assertEqual(realm.max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 1, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": settings.INVITES_DEFAULT_REALM_DAILY_MAX,
|
|
|
|
"new_value": 1,
|
|
|
|
"property": "max_invites",
|
|
|
|
}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
|
|
|
self.assertEqual(realm.max_invites, 1)
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 0, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {"old_value": 1, "new_value": None, "property": "max_invites"}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
|
|
|
self.assertEqual(realm.max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
|
|
|
|
realm.plan_type = Realm.PLAN_TYPE_PLUS
|
|
|
|
realm.save()
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 0, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": settings.INVITES_DEFAULT_REALM_DAILY_MAX,
|
|
|
|
"new_value": Realm.INVITES_STANDARD_REALM_DAILY_MAX,
|
|
|
|
"property": "max_invites",
|
|
|
|
}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_PLUS)
|
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
|
|
|
|
realm.plan_type = Realm.PLAN_TYPE_LIMITED
|
|
|
|
realm.save()
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 0, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": Realm.INVITES_STANDARD_REALM_DAILY_MAX,
|
|
|
|
"new_value": settings.INVITES_DEFAULT_REALM_DAILY_MAX,
|
|
|
|
"property": "max_invites",
|
|
|
|
}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
|
|
|
self.assertEqual(realm.max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
|
|
|
|
realm.plan_type = Realm.PLAN_TYPE_STANDARD
|
|
|
|
realm.save()
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 0, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": settings.INVITES_DEFAULT_REALM_DAILY_MAX,
|
|
|
|
"new_value": Realm.INVITES_STANDARD_REALM_DAILY_MAX,
|
|
|
|
"property": "max_invites",
|
|
|
|
}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD)
|
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
|
|
|
|
realm.plan_type = Realm.PLAN_TYPE_STANDARD_FREE
|
|
|
|
realm.save()
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 50000, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": Realm.INVITES_STANDARD_REALM_DAILY_MAX,
|
|
|
|
"new_value": 50000,
|
|
|
|
"property": "max_invites",
|
|
|
|
}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD_FREE)
|
|
|
|
self.assertEqual(realm.max_invites, 50000)
|
|
|
|
|
|
|
|
do_change_realm_max_invites(realm, 0, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PROPERTY_CHANGED
|
2024-08-22 18:00:14 +02:00
|
|
|
).last()
|
|
|
|
assert realm_audit_log is not None
|
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": 50000,
|
|
|
|
"new_value": Realm.INVITES_STANDARD_REALM_DAILY_MAX,
|
|
|
|
"property": "max_invites",
|
|
|
|
}
|
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD_FREE)
|
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
|
2024-03-13 00:09:01 +01:00
|
|
|
@skipUnless(settings.ZILENCER_ENABLED, "requires zilencer")
|
2021-12-01 02:10:40 +01:00
|
|
|
def test_change_realm_plan_type(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2024-03-13 00:09:01 +01:00
|
|
|
|
|
|
|
# Create additional user, so that the realm has a lot of seats for the purposes
|
|
|
|
# of upload quota calculation.
|
|
|
|
for count in range(10):
|
|
|
|
do_create_user(
|
|
|
|
f"email{count}@example.com",
|
|
|
|
f"password {count}",
|
|
|
|
realm,
|
|
|
|
"name",
|
|
|
|
role=UserProfile.ROLE_MEMBER,
|
|
|
|
acting_user=None,
|
|
|
|
)
|
|
|
|
|
2020-12-04 10:54:15 +01:00
|
|
|
iago = self.example_user("iago")
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
2018-10-17 10:50:59 +02:00
|
|
|
self.assertEqual(realm.max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, None)
|
2019-01-14 11:22:59 +01:00
|
|
|
self.assertEqual(realm.upload_quota_gb, None)
|
2018-10-17 10:50:59 +02:00
|
|
|
|
2024-04-18 12:23:46 +02:00
|
|
|
members_system_group = NamedUserGroup.objects.get(name=SystemGroups.MEMBERS, realm=realm)
|
2023-11-22 12:33:48 +01:00
|
|
|
do_change_realm_permission_group_setting(
|
|
|
|
realm, "can_access_all_users_group", members_system_group, acting_user=None
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.can_access_all_users_group_id, members_system_group.id)
|
|
|
|
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_STANDARD, acting_user=iago)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2020-12-04 10:54:15 +01:00
|
|
|
realm_audit_log = RealmAuditLog.objects.filter(
|
2024-09-03 15:58:19 +02:00
|
|
|
event_type=AuditLogEventType.REALM_PLAN_TYPE_CHANGED
|
2020-12-04 10:54:15 +01:00
|
|
|
).last()
|
2021-07-24 16:56:39 +02:00
|
|
|
assert realm_audit_log is not None
|
2021-10-18 23:28:17 +02:00
|
|
|
expected_extra_data = {
|
|
|
|
"old_value": Realm.PLAN_TYPE_SELF_HOSTED,
|
|
|
|
"new_value": Realm.PLAN_TYPE_STANDARD,
|
|
|
|
}
|
2023-07-13 19:46:06 +02:00
|
|
|
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
2020-12-04 10:54:15 +01:00
|
|
|
self.assertEqual(realm_audit_log.acting_user, iago)
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD)
|
2018-10-17 10:50:59 +02:00
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, None)
|
2024-03-13 00:09:01 +01:00
|
|
|
self.assertEqual(
|
|
|
|
realm.upload_quota_gb, get_seat_count(realm) * settings.UPLOAD_QUOTA_PER_USER_GB
|
|
|
|
)
|
2024-04-18 12:23:46 +02:00
|
|
|
everyone_system_group = NamedUserGroup.objects.get(name=SystemGroups.EVERYONE, realm=realm)
|
2023-11-22 12:33:48 +01:00
|
|
|
self.assertEqual(realm.can_access_all_users_group_id, everyone_system_group.id)
|
2018-10-17 10:50:59 +02:00
|
|
|
|
2022-06-02 15:56:30 +02:00
|
|
|
do_set_realm_property(realm, "enable_spectator_access", True, acting_user=None)
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=iago)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
2018-10-17 10:50:59 +02:00
|
|
|
self.assertEqual(realm.max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, Realm.MESSAGE_VISIBILITY_LIMITED)
|
2019-01-14 11:22:59 +01:00
|
|
|
self.assertEqual(realm.upload_quota_gb, Realm.UPLOAD_QUOTA_LIMITED)
|
2022-06-02 15:56:30 +02:00
|
|
|
self.assertFalse(realm.enable_spectator_access)
|
2018-10-17 10:50:59 +02:00
|
|
|
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_STANDARD_FREE, acting_user=iago)
|
2021-02-12 08:20:45 +01:00
|
|
|
realm = get_realm("zulip")
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD_FREE)
|
2018-10-17 10:50:59 +02:00
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, None)
|
2024-03-13 00:09:01 +01:00
|
|
|
self.assertEqual(realm.upload_quota_gb, Realm.UPLOAD_QUOTA_STANDARD_FREE)
|
2018-10-23 19:25:59 +02:00
|
|
|
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=iago)
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_PLUS, acting_user=iago)
|
2021-09-16 16:05:26 +02:00
|
|
|
realm = get_realm("zulip")
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_PLUS)
|
2021-09-16 16:05:26 +02:00
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, None)
|
2024-03-13 00:09:01 +01:00
|
|
|
self.assertEqual(
|
|
|
|
realm.upload_quota_gb, get_seat_count(realm) * settings.UPLOAD_QUOTA_PER_USER_GB
|
|
|
|
)
|
2020-02-25 08:17:46 +01:00
|
|
|
|
2023-11-22 12:33:48 +01:00
|
|
|
do_change_realm_permission_group_setting(
|
|
|
|
realm, "can_access_all_users_group", members_system_group, acting_user=None
|
|
|
|
)
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_STANDARD, acting_user=iago)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD)
|
|
|
|
self.assertEqual(realm.max_invites, Realm.INVITES_STANDARD_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, None)
|
2024-03-13 00:09:01 +01:00
|
|
|
self.assertEqual(
|
|
|
|
realm.upload_quota_gb, get_seat_count(realm) * settings.UPLOAD_QUOTA_PER_USER_GB
|
|
|
|
)
|
2023-11-22 12:33:48 +01:00
|
|
|
self.assertEqual(realm.can_access_all_users_group_id, everyone_system_group.id)
|
|
|
|
|
2024-03-10 22:57:56 +01:00
|
|
|
# Test that custom_upload_quota_gb overrides the default upload_quota_gb
|
|
|
|
# implied by a plan and makes .upload_quota_gb be unaffacted by plan changes.
|
|
|
|
realm.custom_upload_quota_gb = 100
|
|
|
|
realm.save(update_fields=["custom_upload_quota_gb"])
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_PLUS, acting_user=iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_PLUS)
|
|
|
|
self.assertEqual(realm.upload_quota_gb, 100)
|
|
|
|
|
|
|
|
realm.custom_upload_quota_gb = None
|
|
|
|
realm.save(update_fields=["custom_upload_quota_gb"])
|
|
|
|
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_SELF_HOSTED, acting_user=iago)
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
2020-02-25 08:17:46 +01:00
|
|
|
self.assertEqual(realm.max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
self.assertEqual(realm.message_visibility_limit, None)
|
|
|
|
self.assertEqual(realm.upload_quota_gb, None)
|
|
|
|
|
2024-02-05 23:52:25 +01:00
|
|
|
@override_settings(
|
|
|
|
BILLING_ENABLED=True,
|
|
|
|
AUTHENTICATION_BACKENDS=(
|
|
|
|
"zproject.backends.EmailAuthBackend",
|
|
|
|
"zproject.backends.AzureADAuthBackend",
|
|
|
|
"zproject.backends.SAMLAuthBackend",
|
|
|
|
),
|
|
|
|
)
|
|
|
|
def test_realm_authentication_methods_after_downgrade(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
iago = self.example_user("iago")
|
|
|
|
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_STANDARD, acting_user=iago)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD)
|
|
|
|
|
|
|
|
do_set_realm_authentication_methods(
|
|
|
|
realm, {"Email": True, "AzureAD": True, "SAML": True}, acting_user=None
|
|
|
|
)
|
|
|
|
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=iago)
|
|
|
|
realm.refresh_from_db()
|
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
realm.authentication_methods_dict(),
|
|
|
|
{
|
|
|
|
"Email": True,
|
|
|
|
"AzureAD": False,
|
|
|
|
"SAML": False,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2020-05-09 19:46:56 +02:00
|
|
|
def test_message_retention_days(self) -> None:
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("iago")
|
|
|
|
realm = get_realm("zulip")
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED)
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(10).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-06-15 06:32:10 +02:00
|
|
|
self.assert_json_error(result, "Must be an organization owner")
|
2020-06-11 21:16:53 +02:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("desdemona")
|
2020-06-11 21:16:53 +02:00
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(0).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-05-09 19:46:56 +02:00
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': 0")
|
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(-10).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2021-02-12 08:19:30 +01:00
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': -10")
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
req = dict(message_retention_days=orjson.dumps("invalid").decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-06-21 11:14:35 +02:00
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': invalid")
|
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(-1).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-06-21 11:14:35 +02:00
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': -1")
|
|
|
|
|
2021-08-02 18:43:08 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps("unlimited").decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-05-09 19:46:56 +02:00
|
|
|
self.assert_json_success(result)
|
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(10).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-05-09 19:46:56 +02:00
|
|
|
self.assert_json_success(result)
|
|
|
|
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=None)
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(10).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2022-02-05 08:29:54 +01:00
|
|
|
self.assert_json_error(result, "Available on Zulip Cloud Standard. Upgrade to access.")
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2021-12-01 02:10:40 +01:00
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_STANDARD, acting_user=None)
|
2020-08-07 01:09:47 +02:00
|
|
|
req = dict(message_retention_days=orjson.dumps(10).decode())
|
2021-02-12 08:20:45 +01:00
|
|
|
result = self.client_patch("/json/realm", req)
|
2020-05-19 14:49:48 +02:00
|
|
|
self.assert_json_success(result)
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2023-09-19 19:03:08 +02:00
|
|
|
def test_jitsi_server_url(self) -> None:
|
|
|
|
self.login("iago")
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.video_chat_provider, Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"])
|
|
|
|
|
|
|
|
req = dict(jitsi_server_url=orjson.dumps("").decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "jitsi_server_url is not an allowed_type")
|
|
|
|
|
|
|
|
req = dict(jitsi_server_url=orjson.dumps("invalidURL").decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "jitsi_server_url is not an allowed_type")
|
|
|
|
|
|
|
|
req = dict(jitsi_server_url=orjson.dumps(12).decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
2024-05-17 19:44:28 +02:00
|
|
|
self.assert_json_error(result, "jitsi_server_url is not a string")
|
2023-09-19 19:03:08 +02:00
|
|
|
|
2023-12-14 16:44:18 +01:00
|
|
|
url_string = "".join(random.choices(string.ascii_lowercase, k=180))
|
|
|
|
long_url = "https://jitsi.example.com/" + url_string
|
|
|
|
req = dict(jitsi_server_url=orjson.dumps(long_url).decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "jitsi_server_url is not an allowed_type")
|
|
|
|
|
2023-09-19 19:03:08 +02:00
|
|
|
valid_url = "https://jitsi.example.com"
|
|
|
|
req = dict(jitsi_server_url=orjson.dumps(valid_url).decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.jitsi_server_url, valid_url)
|
|
|
|
|
|
|
|
req = dict(jitsi_server_url=orjson.dumps("default").decode())
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.jitsi_server_url, None)
|
|
|
|
|
2021-04-27 16:56:45 +02:00
|
|
|
def test_do_create_realm(self) -> None:
|
|
|
|
realm = do_create_realm("realm_string_id", "realm name")
|
|
|
|
|
|
|
|
self.assertEqual(realm.string_id, "realm_string_id")
|
|
|
|
self.assertEqual(realm.name, "realm name")
|
|
|
|
self.assertFalse(realm.emails_restricted_to_domains)
|
|
|
|
self.assertEqual(realm.description, "")
|
|
|
|
self.assertTrue(realm.invite_required)
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
2021-06-24 20:05:06 +02:00
|
|
|
self.assertEqual(realm.org_type, Realm.ORG_TYPES["unspecified"]["id"])
|
2023-11-19 19:45:19 +01:00
|
|
|
self.assertEqual(type(realm.date_created), datetime)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
|
|
|
self.assertTrue(
|
|
|
|
RealmAuditLog.objects.filter(
|
2024-09-03 16:46:18 +02:00
|
|
|
realm=realm,
|
|
|
|
event_type=AuditLogEventType.REALM_CREATED,
|
|
|
|
event_time=realm.date_created,
|
2021-04-27 16:56:45 +02:00
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
|
2024-02-07 12:13:02 +01:00
|
|
|
assert realm.new_stream_announcements_stream is not None
|
|
|
|
self.assertEqual(realm.new_stream_announcements_stream.name, "general")
|
|
|
|
self.assertEqual(realm.new_stream_announcements_stream.realm, realm)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
2024-03-29 13:00:12 +01:00
|
|
|
self.assertIsNone(realm.signup_announcements_stream)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_LIMITED)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
2023-08-09 15:06:56 +02:00
|
|
|
for (
|
|
|
|
setting_name,
|
2023-10-31 12:28:49 +01:00
|
|
|
permission_configuration,
|
2023-08-09 15:06:56 +02:00
|
|
|
) in Realm.REALM_PERMISSION_GROUP_SETTINGS.items():
|
|
|
|
self.assertEqual(
|
2024-04-19 16:37:29 +02:00
|
|
|
getattr(realm, setting_name).named_user_group.name,
|
|
|
|
permission_configuration.default_group_name,
|
2023-08-09 15:06:56 +02:00
|
|
|
)
|
|
|
|
|
2021-04-27 16:56:45 +02:00
|
|
|
def test_do_create_realm_with_keyword_arguments(self) -> None:
|
2023-11-19 19:45:19 +01:00
|
|
|
date_created = timezone_now() - timedelta(days=100)
|
2021-04-27 16:56:45 +02:00
|
|
|
realm = do_create_realm(
|
|
|
|
"realm_string_id",
|
|
|
|
"realm name",
|
|
|
|
emails_restricted_to_domains=True,
|
|
|
|
date_created=date_created,
|
|
|
|
description="realm description",
|
|
|
|
invite_required=False,
|
2021-10-18 23:28:17 +02:00
|
|
|
plan_type=Realm.PLAN_TYPE_STANDARD_FREE,
|
2021-06-24 20:05:06 +02:00
|
|
|
org_type=Realm.ORG_TYPES["community"]["id"],
|
2023-05-09 20:22:37 +02:00
|
|
|
enable_read_receipts=True,
|
2021-04-27 16:56:45 +02:00
|
|
|
)
|
|
|
|
self.assertEqual(realm.string_id, "realm_string_id")
|
|
|
|
self.assertEqual(realm.name, "realm name")
|
|
|
|
self.assertTrue(realm.emails_restricted_to_domains)
|
|
|
|
self.assertEqual(realm.description, "realm description")
|
|
|
|
self.assertFalse(realm.invite_required)
|
2021-10-18 23:28:17 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD_FREE)
|
2021-06-24 20:05:06 +02:00
|
|
|
self.assertEqual(realm.org_type, Realm.ORG_TYPES["community"]["id"])
|
2021-04-27 16:56:45 +02:00
|
|
|
self.assertEqual(realm.date_created, date_created)
|
2023-05-09 20:22:37 +02:00
|
|
|
self.assertEqual(realm.enable_read_receipts, True)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
|
|
|
self.assertTrue(
|
|
|
|
RealmAuditLog.objects.filter(
|
2024-09-03 16:46:18 +02:00
|
|
|
realm=realm,
|
|
|
|
event_type=AuditLogEventType.REALM_CREATED,
|
|
|
|
event_time=realm.date_created,
|
2021-04-27 16:56:45 +02:00
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
|
2024-02-07 12:13:02 +01:00
|
|
|
assert realm.new_stream_announcements_stream is not None
|
|
|
|
self.assertEqual(realm.new_stream_announcements_stream.name, "general")
|
|
|
|
self.assertEqual(realm.new_stream_announcements_stream.realm, realm)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
2024-03-29 13:00:12 +01:00
|
|
|
self.assertIsNone(realm.signup_announcements_stream)
|
2021-04-27 16:56:45 +02:00
|
|
|
|
2020-12-24 12:39:27 +01:00
|
|
|
def test_realm_is_web_public(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
# By default "Rome" is web_public in zulip realm
|
|
|
|
rome = Stream.objects.get(name="Rome")
|
|
|
|
self.assertEqual(rome.is_web_public, True)
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), True)
|
2021-09-21 19:49:12 +02:00
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), True)
|
|
|
|
|
|
|
|
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), False)
|
2020-12-24 12:39:27 +01:00
|
|
|
|
2021-11-23 12:23:48 +01:00
|
|
|
realm.enable_spectator_access = False
|
|
|
|
realm.save()
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), False)
|
|
|
|
|
|
|
|
realm.enable_spectator_access = True
|
|
|
|
realm.save()
|
|
|
|
|
2020-12-24 12:39:27 +01:00
|
|
|
# Convert Rome to a public stream
|
|
|
|
rome.is_web_public = False
|
|
|
|
rome.save()
|
|
|
|
self.assertEqual(Stream.objects.filter(realm=realm, is_web_public=True).count(), 0)
|
2021-09-21 19:49:12 +02:00
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), True)
|
2020-12-24 12:39:27 +01:00
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
2021-09-21 19:49:12 +02:00
|
|
|
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
|
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), False)
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
2020-12-24 12:39:27 +01:00
|
|
|
|
|
|
|
# Restore state
|
|
|
|
rome.is_web_public = True
|
|
|
|
rome.save()
|
|
|
|
self.assertEqual(Stream.objects.filter(realm=realm, is_web_public=True).count(), 1)
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), True)
|
2021-09-21 19:49:12 +02:00
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), True)
|
|
|
|
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
|
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), False)
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
2020-12-24 12:39:27 +01:00
|
|
|
|
2021-10-18 23:28:17 +02:00
|
|
|
realm.plan_type = Realm.PLAN_TYPE_LIMITED
|
2020-12-24 12:39:27 +01:00
|
|
|
realm.save()
|
|
|
|
self.assertEqual(Stream.objects.filter(realm=realm, is_web_public=True).count(), 1)
|
2021-09-21 19:49:12 +02:00
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), False)
|
2020-12-24 12:39:27 +01:00
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
2021-09-21 19:49:12 +02:00
|
|
|
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
|
|
|
|
self.assertEqual(realm.web_public_streams_enabled(), False)
|
|
|
|
self.assertEqual(realm.has_web_public_streams(), False)
|
2020-12-24 12:39:27 +01:00
|
|
|
|
2021-08-11 15:10:17 +02:00
|
|
|
def test_creating_realm_creates_system_groups(self) -> None:
|
|
|
|
realm = do_create_realm("realm_string_id", "realm name")
|
2024-04-18 12:23:46 +02:00
|
|
|
system_user_groups = NamedUserGroup.objects.filter(realm=realm, is_system_group=True)
|
2021-08-11 15:10:17 +02:00
|
|
|
|
2023-03-27 05:28:12 +02:00
|
|
|
self.assert_length(system_user_groups, 8)
|
2021-08-11 15:10:17 +02:00
|
|
|
user_group_names = [group.name for group in system_user_groups]
|
|
|
|
expected_system_group_names = [
|
2023-09-21 13:06:39 +02:00
|
|
|
SystemGroups.OWNERS,
|
|
|
|
SystemGroups.ADMINISTRATORS,
|
|
|
|
SystemGroups.MODERATORS,
|
|
|
|
SystemGroups.FULL_MEMBERS,
|
|
|
|
SystemGroups.MEMBERS,
|
|
|
|
SystemGroups.EVERYONE,
|
|
|
|
SystemGroups.EVERYONE_ON_INTERNET,
|
|
|
|
SystemGroups.NOBODY,
|
2021-08-11 15:10:17 +02:00
|
|
|
]
|
2023-10-02 06:47:38 +02:00
|
|
|
self.assertEqual(sorted(user_group_names), sorted(expected_system_group_names))
|
2021-08-11 15:10:17 +02:00
|
|
|
|
2024-07-16 22:52:01 +02:00
|
|
|
@activate_push_notification_service()
|
2023-12-01 14:52:44 +01:00
|
|
|
def test_do_create_realm_notify_bouncer(self) -> None:
|
2023-11-29 17:00:19 +01:00
|
|
|
dummy_send_realms_only_response = {
|
|
|
|
"result": "success",
|
|
|
|
"msg": "",
|
2023-12-10 12:01:51 +01:00
|
|
|
"realms": {},
|
2023-11-29 17:00:19 +01:00
|
|
|
}
|
|
|
|
with mock.patch(
|
|
|
|
"zerver.lib.remote_server.send_to_push_bouncer",
|
|
|
|
) as m:
|
2023-12-09 13:29:59 +01:00
|
|
|
get_response = {
|
|
|
|
"last_realm_count_id": 0,
|
|
|
|
"last_installation_count_id": 0,
|
|
|
|
"last_realmauditlog_id": 0,
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
def mock_send_to_push_bouncer_response(method: str, *args: Any) -> dict[str, Any]:
|
2023-12-09 13:29:59 +01:00
|
|
|
if method == "GET":
|
|
|
|
return get_response
|
|
|
|
return dummy_send_realms_only_response
|
|
|
|
|
|
|
|
m.side_effect = mock_send_to_push_bouncer_response
|
|
|
|
|
2023-12-11 22:12:22 +01:00
|
|
|
with self.captureOnCommitCallbacks(execute=True):
|
|
|
|
realm = do_create_realm("realm_string_id", "realm name")
|
2023-12-01 14:52:44 +01:00
|
|
|
|
|
|
|
self.assertEqual(realm.string_id, "realm_string_id")
|
2023-12-09 13:29:59 +01:00
|
|
|
self.assertEqual(m.call_count, 2)
|
2023-12-01 14:52:44 +01:00
|
|
|
|
2023-12-09 13:29:59 +01:00
|
|
|
calls_args_for_assert = m.call_args_list[1][0]
|
2023-12-01 14:52:44 +01:00
|
|
|
self.assertEqual(calls_args_for_assert[0], "POST")
|
|
|
|
self.assertEqual(calls_args_for_assert[1], "server/analytics")
|
|
|
|
self.assertIn(
|
2023-12-09 13:29:59 +01:00
|
|
|
realm.id, [realm["id"] for realm in json.loads(m.call_args_list[1][0][2]["realms"])]
|
2023-12-01 14:52:44 +01:00
|
|
|
)
|
|
|
|
|
2021-08-17 09:03:09 +02:00
|
|
|
def test_changing_waiting_period_updates_system_groups(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
2024-04-18 12:23:46 +02:00
|
|
|
members_system_group = NamedUserGroup.objects.get(
|
2023-09-21 13:06:39 +02:00
|
|
|
realm=realm, name=SystemGroups.MEMBERS, is_system_group=True
|
2021-08-17 09:03:09 +02:00
|
|
|
)
|
2024-04-18 12:23:46 +02:00
|
|
|
full_members_system_group = NamedUserGroup.objects.get(
|
2023-09-21 13:06:39 +02:00
|
|
|
realm=realm, name=SystemGroups.FULL_MEMBERS, is_system_group=True
|
2021-08-17 09:03:09 +02:00
|
|
|
)
|
|
|
|
|
2023-04-11 19:51:14 +02:00
|
|
|
self.assert_length(UserGroupMembership.objects.filter(user_group=members_system_group), 9)
|
2021-08-17 09:03:09 +02:00
|
|
|
self.assert_length(
|
2023-04-11 19:51:14 +02:00
|
|
|
UserGroupMembership.objects.filter(user_group=full_members_system_group), 9
|
2021-08-17 09:03:09 +02:00
|
|
|
)
|
|
|
|
self.assertEqual(realm.waiting_period_threshold, 0)
|
|
|
|
|
|
|
|
hamlet = self.example_user("hamlet")
|
|
|
|
othello = self.example_user("othello")
|
|
|
|
prospero = self.example_user("prospero")
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=hamlet
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=othello
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=prospero
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=hamlet
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=othello
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=prospero
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
|
|
|
|
hamlet.date_joined = timezone_now() - timedelta(days=50)
|
|
|
|
hamlet.save()
|
|
|
|
othello.date_joined = timezone_now() - timedelta(days=75)
|
|
|
|
othello.save()
|
|
|
|
prospero.date_joined = timezone_now() - timedelta(days=150)
|
|
|
|
prospero.save()
|
|
|
|
do_set_realm_property(realm, "waiting_period_threshold", 100, acting_user=None)
|
|
|
|
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=hamlet
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=othello
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=prospero
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertFalse(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=hamlet
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertFalse(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=othello
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=prospero
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
|
|
|
|
do_set_realm_property(realm, "waiting_period_threshold", 70, acting_user=None)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=hamlet
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=othello
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=members_system_group, user_profile=prospero
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertFalse(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=hamlet
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=othello
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
self.assertTrue(
|
|
|
|
UserGroupMembership.objects.filter(
|
|
|
|
user_group=full_members_system_group, user_profile=prospero
|
|
|
|
).exists()
|
|
|
|
)
|
|
|
|
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
class RealmAPITest(ZulipTestCase):
|
2023-10-12 19:43:45 +02:00
|
|
|
@override
|
2017-11-05 10:51:25 +01:00
|
|
|
def setUp(self) -> None:
|
2019-10-19 20:47:00 +02:00
|
|
|
super().setUp()
|
2021-02-12 08:20:45 +01:00
|
|
|
self.login("desdemona")
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2024-07-12 02:30:23 +02:00
|
|
|
def update_with_api(self, name: str, value: int | str) -> Realm:
|
2021-04-07 22:00:40 +02:00
|
|
|
if not isinstance(value, str):
|
|
|
|
value = orjson.dumps(value).decode()
|
|
|
|
result = self.client_patch("/json/realm", {name: value})
|
2017-04-09 00:35:41 +02:00
|
|
|
self.assert_json_success(result)
|
2021-02-12 08:20:45 +01:00
|
|
|
return get_realm("zulip") # refresh data
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def do_test_realm_update_api(self, name: str) -> None:
|
2017-04-09 00:35:41 +02:00
|
|
|
"""Test updating realm properties.
|
|
|
|
|
|
|
|
If new realm properties have been added to the Realm model but the
|
|
|
|
test_values dict below has not been updated, this will raise an
|
|
|
|
assertion error.
|
|
|
|
"""
|
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
bool_tests: list[bool] = [False, True]
|
|
|
|
test_values: dict[str, Any] = dict(
|
2021-02-12 08:20:45 +01:00
|
|
|
default_language=["de", "en"],
|
|
|
|
default_code_block_language=["javascript", ""],
|
|
|
|
description=["Realm description", "New description"],
|
2019-03-31 12:13:42 +02:00
|
|
|
digest_weekday=[0, 1, 2],
|
2017-04-09 00:35:41 +02:00
|
|
|
message_retention_days=[10, 20],
|
2021-02-12 08:20:45 +01:00
|
|
|
name=["Zulip", "New Name"],
|
2017-04-09 00:35:41 +02:00
|
|
|
waiting_period_threshold=[10, 20],
|
2021-07-06 19:27:39 +02:00
|
|
|
invite_to_stream_policy=Realm.COMMON_POLICY_TYPES,
|
|
|
|
wildcard_mention_policy=Realm.WILDCARD_MENTION_POLICY_TYPES,
|
|
|
|
bot_creation_policy=Realm.BOT_CREATION_POLICY_TYPES,
|
2019-05-10 10:06:50 +02:00
|
|
|
video_chat_provider=[
|
2024-05-14 15:42:37 +02:00
|
|
|
Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"],
|
|
|
|
Realm.VIDEO_CHAT_PROVIDERS["disabled"]["id"],
|
2023-09-19 19:03:08 +02:00
|
|
|
],
|
2024-05-14 15:42:37 +02:00
|
|
|
jitsi_server_url=["https://example.jit.si"],
|
2021-03-31 13:10:46 +02:00
|
|
|
giphy_rating=[
|
|
|
|
Realm.GIPHY_RATING_OPTIONS["y"]["id"],
|
|
|
|
Realm.GIPHY_RATING_OPTIONS["r"]["id"],
|
|
|
|
],
|
2021-02-12 08:19:30 +01:00
|
|
|
message_content_delete_limit_seconds=[1000, 1100, 1200],
|
2021-07-18 10:11:58 +02:00
|
|
|
invite_to_realm_policy=Realm.INVITE_TO_REALM_POLICY_TYPES,
|
2022-09-29 09:03:12 +02:00
|
|
|
move_messages_between_streams_policy=Realm.MOVE_MESSAGES_BETWEEN_STREAMS_POLICY_TYPES,
|
2022-09-28 16:30:10 +02:00
|
|
|
edit_topic_policy=Realm.EDIT_TOPIC_POLICY_TYPES,
|
2022-09-22 10:53:37 +02:00
|
|
|
message_content_edit_limit_seconds=[1000, 1100, 1200],
|
2023-01-26 12:53:27 +01:00
|
|
|
move_messages_within_stream_limit_seconds=[1000, 1100, 1200],
|
2022-10-11 13:19:49 +02:00
|
|
|
move_messages_between_streams_limit_seconds=[1000, 1100, 1200],
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
)
|
2019-05-10 10:06:50 +02:00
|
|
|
|
2017-04-09 00:35:41 +02:00
|
|
|
vals = test_values.get(name)
|
2017-07-04 23:18:29 +02:00
|
|
|
if Realm.property_types[name] is bool:
|
|
|
|
vals = bool_tests
|
2017-04-09 00:35:41 +02:00
|
|
|
if vals is None:
|
2021-02-12 08:20:45 +01:00
|
|
|
raise AssertionError(f"No test created for {name}")
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2024-05-14 15:42:37 +02:00
|
|
|
if name == "jitsi_server_url":
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertIsNone(realm.jitsi_server_url, None)
|
|
|
|
realm = self.update_with_api(name, orjson.dumps(vals[0]).decode())
|
|
|
|
self.assertEqual(realm.jitsi_server_url, vals[0])
|
|
|
|
|
|
|
|
realm = self.update_with_api(name, orjson.dumps("default").decode())
|
|
|
|
self.assertIsNone(realm.jitsi_server_url, None)
|
2021-07-06 19:18:25 +02:00
|
|
|
return
|
|
|
|
|
2024-05-14 13:46:56 +02:00
|
|
|
do_set_realm_property(get_realm("zulip"), name, vals[0], acting_user=None)
|
2021-07-06 19:18:25 +02:00
|
|
|
|
|
|
|
for val in vals[1:]:
|
|
|
|
realm = self.update_with_api(name, val)
|
|
|
|
self.assertEqual(getattr(realm, name), val)
|
|
|
|
|
|
|
|
realm = self.update_with_api(name, vals[0])
|
|
|
|
self.assertEqual(getattr(realm, name), vals[0])
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2023-08-09 15:06:56 +02:00
|
|
|
def do_test_realm_permission_group_setting_update_api(self, setting_name: str) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
|
2024-04-18 12:23:46 +02:00
|
|
|
all_system_user_groups = NamedUserGroup.objects.filter(
|
2023-08-09 15:06:56 +02:00
|
|
|
realm=realm,
|
|
|
|
is_system_group=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
setting_permission_configuration = Realm.REALM_PERMISSION_GROUP_SETTINGS[setting_name]
|
|
|
|
|
|
|
|
default_group_name = setting_permission_configuration.default_group_name
|
|
|
|
default_group = all_system_user_groups.get(name=default_group_name)
|
|
|
|
|
2024-05-14 13:46:56 +02:00
|
|
|
self.assertEqual(getattr(realm, setting_name), default_group.usergroup_ptr)
|
2023-08-09 15:06:56 +02:00
|
|
|
|
|
|
|
for user_group in all_system_user_groups:
|
2024-05-23 16:21:25 +02:00
|
|
|
value = orjson.dumps(user_group.id).decode()
|
|
|
|
if setting_name in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
|
|
|
|
value = orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": user_group.id,
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
|
2023-08-09 15:06:56 +02:00
|
|
|
if (
|
|
|
|
(
|
2023-09-21 13:06:39 +02:00
|
|
|
user_group.name == SystemGroups.EVERYONE_ON_INTERNET
|
2023-08-09 15:06:56 +02:00
|
|
|
and not setting_permission_configuration.allow_internet_group
|
|
|
|
)
|
|
|
|
or (
|
2023-09-21 13:06:39 +02:00
|
|
|
user_group.name == SystemGroups.NOBODY
|
2023-08-09 15:06:56 +02:00
|
|
|
and not setting_permission_configuration.allow_nobody_group
|
|
|
|
)
|
2023-09-07 02:06:51 +02:00
|
|
|
or (
|
2023-09-21 13:06:39 +02:00
|
|
|
user_group.name == SystemGroups.EVERYONE
|
2023-09-07 02:06:51 +02:00
|
|
|
and not setting_permission_configuration.allow_everyone_group
|
|
|
|
)
|
2023-08-09 15:06:56 +02:00
|
|
|
or (
|
2023-09-21 13:06:39 +02:00
|
|
|
user_group.name == SystemGroups.OWNERS
|
2023-08-09 15:06:56 +02:00
|
|
|
and not setting_permission_configuration.allow_owners_group
|
|
|
|
)
|
2023-03-23 15:42:00 +01:00
|
|
|
or (
|
|
|
|
setting_permission_configuration.allowed_system_groups
|
|
|
|
and user_group.name
|
|
|
|
not in setting_permission_configuration.allowed_system_groups
|
|
|
|
)
|
2023-08-09 15:06:56 +02:00
|
|
|
):
|
|
|
|
result = self.client_patch("/json/realm", {setting_name: value})
|
|
|
|
self.assert_json_error(
|
|
|
|
result, f"'{setting_name}' setting cannot be set to '{user_group.name}' group."
|
|
|
|
)
|
|
|
|
continue
|
|
|
|
|
2024-05-23 16:21:25 +02:00
|
|
|
realm = self.update_with_api(setting_name, value)
|
2024-04-18 12:23:46 +02:00
|
|
|
self.assertEqual(getattr(realm, setting_name), user_group.usergroup_ptr)
|
2023-08-09 15:06:56 +02:00
|
|
|
|
2024-07-01 16:48:16 +02:00
|
|
|
if setting_permission_configuration.require_system_group:
|
|
|
|
leadership_group = NamedUserGroup.objects.get(name="leadership", realm=realm)
|
|
|
|
|
|
|
|
value = orjson.dumps(leadership_group.id).decode()
|
|
|
|
if setting_name in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
|
|
|
|
value = orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": leadership_group.id,
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
|
|
|
|
result = self.client_patch("/json/realm", {setting_name: value})
|
|
|
|
self.assert_json_error(result, f"'{setting_name}' must be a system user group.")
|
|
|
|
|
|
|
|
if setting_name in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
|
|
|
|
admins_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.ADMINISTRATORS, realm=realm
|
|
|
|
)
|
|
|
|
moderators_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.MODERATORS, realm=realm
|
|
|
|
)
|
|
|
|
value = orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [],
|
|
|
|
"direct_subgroups": [admins_group.id, leadership_group.id],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
result = self.client_patch("/json/realm", {setting_name: value})
|
|
|
|
self.assert_json_error(result, f"'{setting_name}' must be a system user group.")
|
|
|
|
|
|
|
|
value = orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [],
|
|
|
|
"direct_subgroups": [admins_group.id, moderators_group.id],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
result = self.client_patch("/json/realm", {setting_name: value})
|
|
|
|
self.assert_json_error(result, f"'{setting_name}' must be a system user group.")
|
|
|
|
|
|
|
|
value = orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [],
|
|
|
|
"direct_subgroups": [admins_group.id],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
realm = self.update_with_api(setting_name, value)
|
|
|
|
self.assertEqual(getattr(realm, setting_name), admins_group.usergroup_ptr)
|
|
|
|
|
2024-05-23 16:21:25 +02:00
|
|
|
def do_test_realm_permission_group_setting_update_api_with_anonymous_groups(
|
|
|
|
self, setting_name: str
|
|
|
|
) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
othello = self.example_user("othello")
|
|
|
|
hamlet = self.example_user("hamlet")
|
2024-06-17 12:23:43 +02:00
|
|
|
leadership_group = NamedUserGroup.objects.get(name="leadership", realm=realm)
|
2024-05-23 16:21:25 +02:00
|
|
|
|
|
|
|
moderators_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.MODERATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm", {setting_name: orjson.dumps({"new": moderators_group.id}).decode()}
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(getattr(realm, setting_name), moderators_group.usergroup_ptr)
|
|
|
|
|
|
|
|
# Try passing the old value as well.
|
|
|
|
admins_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{"new": admins_group.id, "old": leadership_group.id}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "'old' value does not match the expected value.")
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": admins_group.id,
|
|
|
|
"old": {
|
|
|
|
"direct_members": [othello.id],
|
|
|
|
"direct_subgroups": [moderators_group.id],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
).decode(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "'old' value does not match the expected value.")
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{"new": admins_group.id, "old": moderators_group.id}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(getattr(realm, setting_name), admins_group.usergroup_ptr)
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [othello.id],
|
|
|
|
"direct_subgroups": [leadership_group.id],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertCountEqual(list(getattr(realm, setting_name).direct_members.all()), [othello])
|
|
|
|
self.assertCountEqual(
|
|
|
|
list(getattr(realm, setting_name).direct_subgroups.all()), [leadership_group]
|
|
|
|
)
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [hamlet.id],
|
|
|
|
"direct_subgroups": [moderators_group.id],
|
|
|
|
},
|
|
|
|
"old": moderators_group.id,
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "'old' value does not match the expected value.")
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [hamlet.id],
|
|
|
|
"direct_subgroups": [moderators_group.id],
|
|
|
|
},
|
|
|
|
"old": {
|
|
|
|
"direct_members": [othello.id],
|
|
|
|
"direct_subgroups": [moderators_group.id],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
).decode(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "'old' value does not match the expected value.")
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [hamlet.id],
|
|
|
|
"direct_subgroups": [moderators_group.id],
|
|
|
|
},
|
|
|
|
"old": {
|
|
|
|
"direct_members": [othello.id],
|
|
|
|
"direct_subgroups": [leadership_group.id],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertCountEqual(list(getattr(realm, setting_name).direct_members.all()), [hamlet])
|
|
|
|
self.assertCountEqual(
|
|
|
|
list(getattr(realm, setting_name).direct_subgroups.all()), [moderators_group]
|
|
|
|
)
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": leadership_group.id,
|
|
|
|
"old": {
|
|
|
|
"direct_members": [hamlet.id],
|
|
|
|
"direct_subgroups": [moderators_group.id],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(getattr(realm, setting_name), leadership_group.usergroup_ptr)
|
|
|
|
|
|
|
|
# Test that object with only one direct_subgroup is considered
|
|
|
|
# same as passing the named user group ID directly.
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm",
|
|
|
|
{
|
|
|
|
setting_name: orjson.dumps(
|
|
|
|
{
|
|
|
|
"new": {
|
|
|
|
"direct_members": [],
|
|
|
|
"direct_subgroups": [admins_group.id],
|
|
|
|
},
|
|
|
|
"old": {
|
|
|
|
"direct_members": [],
|
|
|
|
"direct_subgroups": [leadership_group.id],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
).decode()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(getattr(realm, setting_name), admins_group.usergroup_ptr)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_update_realm_properties(self) -> None:
|
2017-04-09 00:35:41 +02:00
|
|
|
for prop in Realm.property_types:
|
2023-11-23 22:07:41 +01:00
|
|
|
# push_notifications_enabled is maintained by the server, not via the API.
|
|
|
|
if prop != "push_notifications_enabled":
|
|
|
|
with self.subTest(property=prop):
|
|
|
|
self.do_test_realm_update_api(prop)
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2024-09-25 11:51:28 +02:00
|
|
|
hamlet = self.example_user("hamlet")
|
|
|
|
check_add_user_group(get_realm("zulip"), "leadership", [hamlet], acting_user=hamlet)
|
2023-08-09 15:06:56 +02:00
|
|
|
for prop in Realm.REALM_PERMISSION_GROUP_SETTINGS:
|
|
|
|
with self.subTest(property=prop):
|
|
|
|
self.do_test_realm_permission_group_setting_update_api(prop)
|
|
|
|
|
2024-05-23 16:21:25 +02:00
|
|
|
for prop in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
|
2024-07-23 15:56:46 +02:00
|
|
|
if Realm.REALM_PERMISSION_GROUP_SETTINGS[prop].require_system_group:
|
|
|
|
# Anonymous system groups aren't relevant when
|
|
|
|
# restricted to system groups.
|
2024-07-01 16:48:16 +02:00
|
|
|
continue
|
2024-05-23 16:21:25 +02:00
|
|
|
with self.subTest(property=prop):
|
|
|
|
self.do_test_realm_permission_group_setting_update_api_with_anonymous_groups(prop)
|
|
|
|
|
2022-04-11 19:26:16 +02:00
|
|
|
# Not in Realm.property_types because org_type has
|
|
|
|
# a unique RealmAuditLog event_type.
|
|
|
|
def test_update_realm_org_type(self) -> None:
|
|
|
|
vals = [t["id"] for t in Realm.ORG_TYPES.values()]
|
|
|
|
|
2024-05-14 13:46:56 +02:00
|
|
|
do_change_realm_org_type(get_realm("zulip"), vals[0], acting_user=None)
|
2022-04-11 19:26:16 +02:00
|
|
|
|
|
|
|
for val in vals[1:]:
|
|
|
|
realm = self.update_with_api("org_type", val)
|
2022-06-26 20:41:49 +02:00
|
|
|
self.assertEqual(realm.org_type, val)
|
2022-04-11 19:26:16 +02:00
|
|
|
|
|
|
|
realm = self.update_with_api("org_type", vals[0])
|
2022-06-26 20:41:49 +02:00
|
|
|
self.assertEqual(realm.org_type, vals[0])
|
2022-04-11 19:26:16 +02:00
|
|
|
|
|
|
|
# Now we test an invalid org_type id.
|
|
|
|
invalid_org_type = 1
|
|
|
|
assert invalid_org_type not in vals
|
|
|
|
result = self.client_patch("/json/realm", {"org_type": invalid_org_type})
|
|
|
|
self.assert_json_error(result, "Invalid org_type")
|
|
|
|
|
2021-07-21 13:23:23 +02:00
|
|
|
def update_with_realm_default_api(self, name: str, val: Any) -> None:
|
|
|
|
if not isinstance(val, str):
|
|
|
|
val = orjson.dumps(val).decode()
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", {name: val})
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
def do_test_realm_default_setting_update_api(self, name: str) -> None:
|
2024-07-12 02:30:17 +02:00
|
|
|
bool_tests: list[bool] = [False, True]
|
|
|
|
test_values: dict[str, Any] = dict(
|
2024-07-18 02:07:12 +02:00
|
|
|
web_font_size_px=[UserProfile.WEB_FONT_SIZE_PX_COMPACT],
|
|
|
|
web_line_height_percent=[UserProfile.WEB_LINE_HEIGHT_PERCENT_COMPACT],
|
2021-07-21 13:23:23 +02:00
|
|
|
color_scheme=UserProfile.COLOR_SCHEME_CHOICES,
|
2023-10-23 09:02:57 +02:00
|
|
|
web_home_view=["recent_topics", "inbox", "all_messages"],
|
2021-07-21 13:23:23 +02:00
|
|
|
emojiset=[emojiset["key"] for emojiset in RealmUserDefault.emojiset_choices()],
|
|
|
|
demote_inactive_streams=UserProfile.DEMOTE_STREAMS_CHOICES,
|
2023-04-05 21:35:47 +02:00
|
|
|
web_mark_read_on_scroll_policy=UserProfile.WEB_MARK_READ_ON_SCROLL_POLICY_CHOICES,
|
2024-07-03 12:43:47 +02:00
|
|
|
web_channel_default_view=UserProfile.WEB_CHANNEL_DEFAULT_VIEW_CHOICES,
|
2022-08-12 22:41:06 +02:00
|
|
|
user_list_style=UserProfile.USER_LIST_STYLE_CHOICES,
|
2024-07-21 15:23:56 +02:00
|
|
|
web_animate_image_previews=["always", "on_hover", "never"],
|
2023-04-25 12:29:15 +02:00
|
|
|
web_stream_unreads_count_display_policy=UserProfile.WEB_STREAM_UNREADS_COUNT_DISPLAY_POLICY_CHOICES,
|
2023-09-14 11:25:02 +02:00
|
|
|
desktop_icon_count_display=UserProfile.DESKTOP_ICON_COUNT_DISPLAY_CHOICES,
|
2021-07-21 13:23:23 +02:00
|
|
|
notification_sound=["zulip", "ding"],
|
|
|
|
email_notifications_batching_period_seconds=[120, 300],
|
2021-10-21 10:36:57 +02:00
|
|
|
email_address_visibility=UserProfile.EMAIL_ADDRESS_VISIBILITY_TYPES,
|
2023-01-14 20:36:37 +01:00
|
|
|
realm_name_in_email_notifications_policy=UserProfile.REALM_NAME_IN_EMAIL_NOTIFICATIONS_POLICY_CHOICES,
|
2023-06-17 17:37:04 +02:00
|
|
|
automatically_follow_topics_policy=UserProfile.AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_CHOICES,
|
|
|
|
automatically_unmute_topics_in_muted_streams_policy=UserProfile.AUTOMATICALLY_CHANGE_VISIBILITY_POLICY_CHOICES,
|
2023-12-10 14:53:52 +01:00
|
|
|
automatically_follow_topics_where_mentioned=[True, False],
|
2021-07-21 13:23:23 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
vals = test_values.get(name)
|
|
|
|
property_type = RealmUserDefault.property_types[name]
|
|
|
|
|
|
|
|
if property_type is bool:
|
|
|
|
vals = bool_tests
|
|
|
|
|
|
|
|
if vals is None:
|
|
|
|
raise AssertionError(f"No test created for {name}")
|
|
|
|
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
do_set_realm_user_default_setting(realm_user_default, name, vals[0], acting_user=None)
|
|
|
|
|
|
|
|
for val in vals[1:]:
|
|
|
|
self.update_with_realm_default_api(name, val)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(getattr(realm_user_default, name), val)
|
|
|
|
|
|
|
|
self.update_with_realm_default_api(name, vals[0])
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(getattr(realm_user_default, name), vals[0])
|
|
|
|
|
|
|
|
def test_update_default_realm_settings(self) -> None:
|
|
|
|
for prop in RealmUserDefault.property_types:
|
|
|
|
# enable_marketing_emails setting is not actually used and thus cannot be updated
|
|
|
|
# using this endpoint. It is included in notification_setting_types only for avoiding
|
2021-09-17 18:11:37 +02:00
|
|
|
# duplicate code. default_language is currently present in Realm table also and thus
|
|
|
|
# is updated using '/realm' endpoint, but this will be removed in future and the
|
|
|
|
# settings in RealmUserDefault table will be used.
|
2024-09-09 12:51:38 +02:00
|
|
|
if prop in [
|
|
|
|
"default_language",
|
|
|
|
"enable_login_emails",
|
|
|
|
"enable_marketing_emails",
|
|
|
|
"allow_private_data_export",
|
|
|
|
]:
|
2021-07-21 13:23:23 +02:00
|
|
|
continue
|
2024-07-18 02:07:12 +02:00
|
|
|
if prop in ["dense_mode"]:
|
|
|
|
# Testing this is complicated, see test_update_default_information_density_settings.
|
|
|
|
continue
|
2021-07-21 13:23:23 +02:00
|
|
|
self.do_test_realm_default_setting_update_api(prop)
|
|
|
|
|
2024-07-03 15:43:52 +02:00
|
|
|
def test_update_default_information_density_settings(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
2024-07-18 02:07:12 +02:00
|
|
|
|
|
|
|
# Start with the legacy settings configuration
|
2024-07-03 15:43:52 +02:00
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
2024-07-18 02:07:12 +02:00
|
|
|
realm_user_default.dense_mode = True
|
|
|
|
realm_user_default.web_font_size_px = RealmUserDefault.WEB_FONT_SIZE_PX_COMPACT
|
|
|
|
realm_user_default.web_line_height_percent = (
|
|
|
|
RealmUserDefault.WEB_LINE_HEIGHT_PERCENT_COMPACT
|
|
|
|
)
|
|
|
|
realm_user_default.save()
|
2024-07-03 15:43:52 +02:00
|
|
|
self.login("iago")
|
|
|
|
|
2024-07-18 11:05:37 +02:00
|
|
|
data: dict[str, str | int] = {"web_font_size_px": 16}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_error(
|
|
|
|
result,
|
2024-07-18 21:29:40 +02:00
|
|
|
"Incompatible values for 'dense_mode' and 'web_font_size_px'.",
|
2024-07-18 11:05:37 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
data = {"web_font_size_px": 16, "dense_mode": orjson.dumps(False).decode()}
|
2024-07-03 15:43:52 +02:00
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_font_size_px, 16)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, False)
|
|
|
|
|
2024-07-18 11:05:37 +02:00
|
|
|
data = {"web_font_size_px": 20}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_font_size_px, 20)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, False)
|
|
|
|
|
|
|
|
# Check dense_mode is still false when both the
|
|
|
|
# settings are set to legacy values.
|
2024-07-03 15:43:52 +02:00
|
|
|
data = {"web_font_size_px": 14}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_font_size_px, 14)
|
2024-07-18 11:05:37 +02:00
|
|
|
self.assertEqual(realm_user_default.web_line_height_percent, 122)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, False)
|
|
|
|
|
|
|
|
data = {"dense_mode": orjson.dumps(True).decode()}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_font_size_px, 14)
|
2024-07-03 15:43:52 +02:00
|
|
|
self.assertEqual(realm_user_default.dense_mode, True)
|
|
|
|
|
|
|
|
data = {"web_line_height_percent": 140}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
2024-07-18 11:05:37 +02:00
|
|
|
self.assert_json_error(
|
|
|
|
result,
|
2024-07-18 21:29:40 +02:00
|
|
|
"Incompatible values for 'dense_mode' and 'web_line_height_percent'.",
|
2024-07-18 11:05:37 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
data = {"web_line_height_percent": 140, "dense_mode": orjson.dumps(False).decode()}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
2024-07-03 15:43:52 +02:00
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_line_height_percent, 140)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, False)
|
|
|
|
|
2024-07-18 11:05:37 +02:00
|
|
|
data = {"web_line_height_percent": 130}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_line_height_percent, 130)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, False)
|
|
|
|
|
|
|
|
# Check dense_mode is still false when both the
|
|
|
|
# settings are set to legacy values.
|
|
|
|
data = {"web_line_height_percent": 122}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_font_size_px, 14)
|
|
|
|
self.assertEqual(realm_user_default.web_line_height_percent, 122)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, False)
|
|
|
|
|
|
|
|
data = {"dense_mode": orjson.dumps(True).decode(), "web_font_size_px": 16}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
2024-07-15 12:12:17 +02:00
|
|
|
self.assert_json_error(
|
|
|
|
result,
|
2024-07-18 21:29:40 +02:00
|
|
|
"Incompatible values for 'dense_mode' and 'web_font_size_px'.",
|
2024-07-15 12:12:17 +02:00
|
|
|
)
|
|
|
|
|
2024-07-18 11:05:37 +02:00
|
|
|
data = {"dense_mode": orjson.dumps(True).decode(), "web_line_height_percent": 140}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
2024-07-15 12:12:17 +02:00
|
|
|
self.assert_json_error(
|
|
|
|
result,
|
2024-07-18 21:29:40 +02:00
|
|
|
"Incompatible values for 'dense_mode' and 'web_line_height_percent'.",
|
2024-07-15 12:12:17 +02:00
|
|
|
)
|
|
|
|
|
2024-07-18 11:05:37 +02:00
|
|
|
data = {
|
|
|
|
"dense_mode": orjson.dumps(True).decode(),
|
|
|
|
"web_font_size_px": 14,
|
|
|
|
"web_line_height_percent": 122,
|
|
|
|
}
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.web_font_size_px, 14)
|
|
|
|
self.assertEqual(realm_user_default.web_line_height_percent, 122)
|
|
|
|
self.assertEqual(realm_user_default.dense_mode, True)
|
|
|
|
|
2021-07-21 13:23:23 +02:00
|
|
|
def test_invalid_default_notification_sound_value(self) -> None:
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm/user_settings_defaults", {"notification_sound": "invalid"}
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "Invalid notification sound 'invalid'")
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm/user_settings_defaults", {"notification_sound": "zulip"}
|
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.notification_sound, "zulip")
|
|
|
|
|
|
|
|
def test_invalid_email_notifications_batching_period_setting(self) -> None:
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm/user_settings_defaults",
|
|
|
|
{"email_notifications_batching_period_seconds": -1},
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "Invalid email batching period: -1 seconds")
|
|
|
|
|
|
|
|
result = self.client_patch(
|
|
|
|
"/json/realm/user_settings_defaults",
|
|
|
|
{"email_notifications_batching_period_seconds": 7 * 24 * 60 * 60 + 10},
|
|
|
|
)
|
|
|
|
self.assert_json_error(result, "Invalid email batching period: 604810 seconds")
|
|
|
|
|
2024-07-12 17:49:28 +02:00
|
|
|
def test_invalid_emojiset_value(self) -> None:
|
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", {"emojiset": "invalid"})
|
|
|
|
self.assert_json_error(
|
|
|
|
result, "Invalid emojiset: Value error, Not in the list of possible values"
|
|
|
|
)
|
|
|
|
|
2021-07-21 13:23:23 +02:00
|
|
|
def test_ignored_parameters_in_realm_default_endpoint(self) -> None:
|
|
|
|
params = {"starred_message_counts": orjson.dumps(False).decode(), "emoji_set": "twitter"}
|
2022-08-25 18:31:21 +02:00
|
|
|
result = self.client_patch("/json/realm/user_settings_defaults", params)
|
|
|
|
self.assert_json_success(result, ignored_parameters=["emoji_set"])
|
2021-07-21 13:23:23 +02:00
|
|
|
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
realm_user_default = RealmUserDefault.objects.get(realm=realm)
|
|
|
|
self.assertEqual(realm_user_default.starred_message_counts, False)
|
|
|
|
|
2023-01-26 12:53:27 +01:00
|
|
|
def test_update_realm_move_messages_within_stream_limit_seconds_unlimited_value(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.login("iago")
|
|
|
|
realm = self.update_with_api(
|
|
|
|
"move_messages_within_stream_limit_seconds", orjson.dumps("unlimited").decode()
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.move_messages_within_stream_limit_seconds, None)
|
|
|
|
|
2022-10-11 13:19:49 +02:00
|
|
|
def test_update_realm_move_messages_between_streams_limit_seconds_unlimited_value(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.login("iago")
|
|
|
|
realm = self.update_with_api(
|
|
|
|
"move_messages_between_streams_limit_seconds", orjson.dumps("unlimited").decode()
|
|
|
|
)
|
|
|
|
self.assertEqual(realm.move_messages_between_streams_limit_seconds, None)
|
|
|
|
|
2021-07-28 18:23:39 +02:00
|
|
|
def do_test_changing_settings_by_owners_only(self, setting_name: str) -> None:
|
2024-07-12 02:30:17 +02:00
|
|
|
bool_tests: list[bool] = [False, True]
|
|
|
|
test_values: dict[str, Any] = dict(
|
2024-05-22 11:43:10 +02:00
|
|
|
invite_to_realm_policy=[
|
|
|
|
InviteToRealmPolicyEnum.MEMBERS_ONLY,
|
|
|
|
InviteToRealmPolicyEnum.ADMINS_ONLY,
|
|
|
|
],
|
2021-07-29 09:57:58 +02:00
|
|
|
waiting_period_threshold=[10, 20],
|
2021-07-28 18:23:39 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
vals = test_values.get(setting_name)
|
|
|
|
if Realm.property_types[setting_name] is bool:
|
|
|
|
vals = bool_tests
|
|
|
|
assert vals is not None
|
|
|
|
|
2024-05-14 13:46:56 +02:00
|
|
|
do_set_realm_property(get_realm("zulip"), setting_name, vals[0], acting_user=None)
|
2021-07-28 18:23:39 +02:00
|
|
|
value = vals[1]
|
|
|
|
|
|
|
|
if not isinstance(value, str):
|
|
|
|
value = orjson.dumps(value).decode()
|
|
|
|
|
2021-07-19 11:47:42 +02:00
|
|
|
self.login("iago")
|
2021-07-28 18:23:39 +02:00
|
|
|
result = self.client_patch("/json/realm", {setting_name: value})
|
2021-07-19 11:47:42 +02:00
|
|
|
self.assert_json_error(result, "Must be an organization owner")
|
|
|
|
|
|
|
|
self.login("desdemona")
|
2021-07-28 18:23:39 +02:00
|
|
|
result = self.client_patch("/json/realm", {setting_name: value})
|
2021-07-19 11:47:42 +02:00
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
2021-07-28 18:23:39 +02:00
|
|
|
self.assertEqual(getattr(realm, setting_name), vals[1])
|
|
|
|
|
|
|
|
def test_changing_user_joining_settings_require_owners(self) -> None:
|
|
|
|
self.do_test_changing_settings_by_owners_only("invite_to_realm_policy")
|
|
|
|
self.do_test_changing_settings_by_owners_only("invite_required")
|
2021-07-28 18:43:09 +02:00
|
|
|
self.do_test_changing_settings_by_owners_only("emails_restricted_to_domains")
|
|
|
|
self.do_test_changing_settings_by_owners_only("disallow_disposable_email_addresses")
|
2021-07-29 09:57:58 +02:00
|
|
|
self.do_test_changing_settings_by_owners_only("waiting_period_threshold")
|
2021-07-19 11:47:42 +02:00
|
|
|
|
2024-09-13 20:37:43 +02:00
|
|
|
def do_test_changing_groups_setting_by_owners_only(self, setting_name: str) -> None:
|
2024-09-13 15:45:49 +02:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
admins_group = NamedUserGroup.objects.get(
|
|
|
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
|
|
|
)
|
|
|
|
|
|
|
|
self.login("iago")
|
|
|
|
result = self.client_patch(
|
2024-09-13 20:37:43 +02:00
|
|
|
"/json/realm", {setting_name: orjson.dumps({"new": admins_group.id}).decode()}
|
2024-09-13 15:45:49 +02:00
|
|
|
)
|
|
|
|
self.assert_json_error(result, "Must be an organization owner")
|
|
|
|
|
|
|
|
self.login("desdemona")
|
|
|
|
result = self.client_patch(
|
2024-09-13 20:37:43 +02:00
|
|
|
"/json/realm", {setting_name: orjson.dumps({"new": admins_group.id}).decode()}
|
2024-09-13 15:45:49 +02:00
|
|
|
)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
2024-09-13 20:37:43 +02:00
|
|
|
self.assertEqual(getattr(realm, setting_name).id, admins_group.id)
|
|
|
|
|
|
|
|
def test_can_create_groups_setting_requires_owner(self) -> None:
|
|
|
|
self.do_test_changing_groups_setting_by_owners_only("can_create_groups")
|
|
|
|
|
|
|
|
def test_can_manage_all_groups_setting_requires_owner(self) -> None:
|
|
|
|
self.do_test_changing_groups_setting_by_owners_only("can_manage_all_groups")
|
2024-09-13 15:45:49 +02:00
|
|
|
|
2022-08-03 12:24:39 +02:00
|
|
|
def test_enable_spectator_access_for_limited_plan_realms(self) -> None:
|
|
|
|
self.login("iago")
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=None)
|
|
|
|
self.assertFalse(realm.enable_spectator_access)
|
|
|
|
|
|
|
|
req = {"enable_spectator_access": orjson.dumps(True).decode()}
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "Available on Zulip Cloud Standard. Upgrade to access.")
|
|
|
|
|
2023-11-22 12:33:48 +01:00
|
|
|
def test_changing_can_access_all_users_group_based_on_plan_type(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=None)
|
|
|
|
self.login("iago")
|
|
|
|
|
2024-04-18 12:23:46 +02:00
|
|
|
members_group = NamedUserGroup.objects.get(name="role:members", realm=realm)
|
2023-11-22 12:33:48 +01:00
|
|
|
req = {"can_access_all_users_group": orjson.dumps(members_group.id).decode()}
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "Available on Zulip Cloud Plus. Upgrade to access.")
|
|
|
|
|
|
|
|
do_change_realm_plan_type(realm, Realm.PLAN_TYPE_STANDARD, acting_user=None)
|
|
|
|
req = {"can_access_all_users_group": orjson.dumps(members_group.id).decode()}
|
|
|
|
result = self.client_patch("/json/realm", req)
|
|
|
|
self.assert_json_error(result, "Available on Zulip Cloud Plus. Upgrade to access.")
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-09-14 13:14:40 +02:00
|
|
|
class ScrubRealmTest(ZulipTestCase):
|
2023-02-28 04:44:29 +01:00
|
|
|
def test_do_delete_all_realm_attachments(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
hamlet = self.example_user("hamlet")
|
|
|
|
Attachment.objects.filter(realm=realm).delete()
|
|
|
|
assert settings.LOCAL_UPLOADS_DIR is not None
|
|
|
|
assert settings.LOCAL_FILES_DIR is not None
|
|
|
|
|
|
|
|
path_ids = []
|
|
|
|
for n in range(1, 4):
|
|
|
|
content = f"content{n}".encode()
|
2024-08-30 04:13:01 +02:00
|
|
|
url = upload_message_attachment(f"dummy{n}.txt", "text/plain", content, hamlet)[0]
|
2023-02-28 04:44:29 +01:00
|
|
|
base = "/user_uploads/"
|
|
|
|
self.assertEqual(base, url[: len(base)])
|
2024-04-26 20:30:22 +02:00
|
|
|
path_id = re.sub(r"/user_uploads/", "", url)
|
2023-02-28 04:44:29 +01:00
|
|
|
self.assertTrue(os.path.isfile(os.path.join(settings.LOCAL_FILES_DIR, path_id)))
|
|
|
|
path_ids.append(path_id)
|
|
|
|
|
|
|
|
with mock.patch(
|
|
|
|
"zerver.actions.realm_settings.delete_message_attachments",
|
|
|
|
side_effect=delete_message_attachments,
|
|
|
|
) as p:
|
|
|
|
do_delete_all_realm_attachments(realm, batch_size=2)
|
|
|
|
|
|
|
|
self.assertEqual(p.call_count, 2)
|
|
|
|
p.assert_has_calls(
|
|
|
|
[
|
|
|
|
mock.call([path_ids[0], path_ids[1]]),
|
|
|
|
mock.call([path_ids[2]]),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.assertEqual(Attachment.objects.filter(realm=realm).count(), 0)
|
|
|
|
for file_path in path_ids:
|
|
|
|
self.assertFalse(os.path.isfile(os.path.join(settings.LOCAL_FILES_DIR, path_id)))
|
|
|
|
|
2018-09-14 13:14:40 +02:00
|
|
|
def test_scrub_realm(self) -> None:
|
|
|
|
zulip = get_realm("zulip")
|
|
|
|
lear = get_realm("lear")
|
2020-05-13 18:09:17 +02:00
|
|
|
internal_realm = get_realm(settings.SYSTEM_BOT_REALM)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
2023-02-28 03:35:01 +01:00
|
|
|
hamlet = self.example_user("hamlet")
|
2018-09-14 13:14:40 +02:00
|
|
|
iago = self.example_user("iago")
|
|
|
|
othello = self.example_user("othello")
|
|
|
|
|
|
|
|
cordelia = self.lear_user("cordelia")
|
|
|
|
king = self.lear_user("king")
|
|
|
|
|
2020-05-13 18:09:17 +02:00
|
|
|
notification_bot = get_system_bot(settings.NOTIFICATION_BOT, internal_realm.id)
|
|
|
|
|
2018-09-14 13:14:40 +02:00
|
|
|
create_stream_if_needed(lear, "Shakespeare")
|
|
|
|
|
|
|
|
self.subscribe(cordelia, "Shakespeare")
|
|
|
|
self.subscribe(king, "Shakespeare")
|
|
|
|
|
|
|
|
Message.objects.all().delete()
|
|
|
|
UserMessage.objects.all().delete()
|
|
|
|
|
|
|
|
for i in range(5):
|
2020-03-07 11:43:05 +01:00
|
|
|
self.send_stream_message(iago, "Scotland")
|
|
|
|
self.send_stream_message(othello, "Scotland")
|
|
|
|
self.send_stream_message(cordelia, "Shakespeare")
|
|
|
|
self.send_stream_message(king, "Shakespeare")
|
2018-09-14 13:14:40 +02:00
|
|
|
|
2020-05-13 18:09:17 +02:00
|
|
|
internal_send_stream_message(
|
|
|
|
notification_bot, get_stream("Scotland", zulip), "test", "test"
|
|
|
|
)
|
|
|
|
internal_send_private_message(notification_bot, othello, "test")
|
2024-07-04 14:05:48 +02:00
|
|
|
internal_send_group_direct_message(
|
2024-04-01 11:04:28 +02:00
|
|
|
zulip, notification_bot, "test", emails=[othello.email, iago.email]
|
|
|
|
)
|
2020-05-13 18:09:17 +02:00
|
|
|
|
|
|
|
internal_send_stream_message(
|
|
|
|
notification_bot, get_stream("Shakespeare", lear), "test", "test"
|
|
|
|
)
|
|
|
|
internal_send_private_message(notification_bot, king, "test")
|
2024-07-04 14:05:48 +02:00
|
|
|
internal_send_group_direct_message(
|
2024-04-01 11:04:28 +02:00
|
|
|
lear, notification_bot, "test", emails=[cordelia.email, king.email]
|
|
|
|
)
|
2020-05-13 18:09:17 +02:00
|
|
|
|
2018-09-14 13:14:40 +02:00
|
|
|
Attachment.objects.filter(realm=zulip).delete()
|
|
|
|
Attachment.objects.filter(realm=lear).delete()
|
2023-02-28 03:35:01 +01:00
|
|
|
assert settings.LOCAL_UPLOADS_DIR is not None
|
|
|
|
assert settings.LOCAL_FILES_DIR is not None
|
|
|
|
file_paths = []
|
|
|
|
for n, owner in enumerate([iago, othello, hamlet, cordelia, king]):
|
|
|
|
content = f"content{n}".encode()
|
2024-08-30 04:13:01 +02:00
|
|
|
url = upload_message_attachment(f"dummy{n}.txt", "text/plain", content, owner)[0]
|
2023-02-28 03:35:01 +01:00
|
|
|
base = "/user_uploads/"
|
|
|
|
self.assertEqual(base, url[: len(base)])
|
2024-04-26 20:30:22 +02:00
|
|
|
file_path = os.path.join(settings.LOCAL_FILES_DIR, re.sub(r"/user_uploads/", "", url))
|
2023-02-28 03:35:01 +01:00
|
|
|
self.assertTrue(os.path.isfile(file_path))
|
|
|
|
file_paths.append(file_path)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
CustomProfileField.objects.create(realm=lear)
|
|
|
|
|
2023-08-30 21:19:37 +02:00
|
|
|
self.assertEqual(
|
|
|
|
Message.objects.filter(
|
|
|
|
realm_id__in=(zulip.id, lear.id), sender__in=[iago, othello]
|
|
|
|
).count(),
|
|
|
|
10,
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
Message.objects.filter(
|
|
|
|
realm_id__in=(zulip.id, lear.id), sender__in=[cordelia, king]
|
|
|
|
).count(),
|
|
|
|
10,
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
Message.objects.filter(
|
|
|
|
realm_id__in=(zulip.id, lear.id), sender=notification_bot
|
|
|
|
).count(),
|
|
|
|
6,
|
|
|
|
)
|
2020-05-13 18:09:17 +02:00
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[iago, othello]).count(), 25)
|
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[cordelia, king]).count(), 25)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
self.assertNotEqual(CustomProfileField.objects.filter(realm=zulip).count(), 0)
|
|
|
|
|
2020-10-29 20:21:18 +01:00
|
|
|
with self.assertLogs(level="WARNING"):
|
2021-04-02 17:33:33 +02:00
|
|
|
do_scrub_realm(zulip, acting_user=None)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
2023-08-30 21:19:37 +02:00
|
|
|
self.assertEqual(
|
|
|
|
Message.objects.filter(
|
|
|
|
realm_id__in=(zulip.id, lear.id), sender__in=[iago, othello]
|
|
|
|
).count(),
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
Message.objects.filter(
|
|
|
|
realm_id__in=(zulip.id, lear.id), sender__in=[cordelia, king]
|
|
|
|
).count(),
|
|
|
|
10,
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
Message.objects.filter(
|
|
|
|
realm_id__in=(zulip.id, lear.id), sender=notification_bot
|
|
|
|
).count(),
|
|
|
|
3,
|
|
|
|
)
|
2018-09-14 13:14:40 +02:00
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[iago, othello]).count(), 0)
|
2020-05-13 18:09:17 +02:00
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[cordelia, king]).count(), 25)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
self.assertEqual(Attachment.objects.filter(realm=zulip).count(), 0)
|
|
|
|
self.assertEqual(Attachment.objects.filter(realm=lear).count(), 2)
|
|
|
|
|
2023-02-28 03:35:01 +01:00
|
|
|
# Zulip realm files don't exist on disk, Lear ones do
|
|
|
|
self.assertFalse(os.path.isfile(file_paths[0]))
|
|
|
|
self.assertFalse(os.path.isfile(file_paths[1]))
|
|
|
|
self.assertFalse(os.path.isfile(file_paths[2]))
|
|
|
|
self.assertTrue(os.path.isfile(file_paths[3]))
|
|
|
|
self.assertTrue(os.path.isfile(file_paths[4]))
|
|
|
|
|
2018-09-14 13:14:40 +02:00
|
|
|
self.assertEqual(CustomProfileField.objects.filter(realm=zulip).count(), 0)
|
|
|
|
self.assertNotEqual(CustomProfileField.objects.filter(realm=lear).count(), 0)
|
|
|
|
|
|
|
|
zulip_users = UserProfile.objects.filter(realm=zulip)
|
|
|
|
for user in zulip_users:
|
2022-07-27 23:33:49 +02:00
|
|
|
self.assertRegex(user.full_name, r"^Scrubbed [a-z0-9]{15}$")
|
|
|
|
self.assertRegex(user.email, rf"^scrubbed-[a-z0-9]{{15}}@{re.escape(zulip.host)}$")
|
|
|
|
self.assertRegex(
|
|
|
|
user.delivery_email, rf"^scrubbed-[a-z0-9]{{15}}@{re.escape(zulip.host)}$"
|
|
|
|
)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
lear_users = UserProfile.objects.filter(realm=lear)
|
|
|
|
for user in lear_users:
|
2022-07-27 23:33:49 +02:00
|
|
|
self.assertNotRegex(user.full_name, r"^Scrubbed [a-z0-9]{15}$")
|
|
|
|
self.assertNotRegex(user.email, rf"^scrubbed-[a-z0-9]{{15}}@{re.escape(zulip.host)}$")
|
|
|
|
self.assertNotRegex(
|
|
|
|
user.delivery_email, rf"^scrubbed-[a-z0-9]{{15}}@{re.escape(zulip.host)}$"
|
|
|
|
)
|