2017-07-01 03:56:40 +02:00
|
|
|
import datetime
|
2018-09-14 13:14:40 +02:00
|
|
|
import re
|
2020-06-11 00:54:34 +02:00
|
|
|
from typing import Any, Dict, List, Mapping
|
|
|
|
from unittest import mock
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
import ujson
|
2018-10-23 19:25:59 +02:00
|
|
|
from django.conf import settings
|
2017-03-08 12:15:16 +01:00
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
from confirmation.models import Confirmation, create_confirmation_link
|
2017-03-18 20:19:44 +01:00
|
|
|
from zerver.lib.actions import (
|
2020-06-11 00:54:34 +02:00
|
|
|
do_change_plan_type,
|
2018-11-15 23:29:04 +01:00
|
|
|
do_change_realm_subdomain,
|
2020-06-11 00:54:34 +02:00
|
|
|
do_create_realm,
|
2017-03-18 20:19:44 +01:00
|
|
|
do_deactivate_realm,
|
2017-08-24 00:36:29 +02:00
|
|
|
do_deactivate_stream,
|
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,
|
2020-06-11 00:54:34 +02:00
|
|
|
do_set_realm_property,
|
2017-03-18 20:19:44 +01:00
|
|
|
)
|
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
|
2020-06-11 00:54:34 +02:00
|
|
|
from zerver.lib.test_helpers import reset_emails_in_zulip_realm, tornado_redirected_to_list
|
|
|
|
from zerver.models import (
|
|
|
|
Attachment,
|
|
|
|
CustomProfileField,
|
|
|
|
Message,
|
|
|
|
Realm,
|
|
|
|
ScheduledEmail,
|
|
|
|
UserMessage,
|
|
|
|
UserProfile,
|
|
|
|
get_realm,
|
|
|
|
get_stream,
|
|
|
|
get_user_profile_by_email,
|
|
|
|
get_user_profile_by_id,
|
|
|
|
)
|
|
|
|
|
2017-03-08 12:15:16 +01:00
|
|
|
|
|
|
|
class RealmTest(ZulipTestCase):
|
2017-11-17 07:00:53 +01:00
|
|
|
def assert_user_profile_cache_gets_new_name(self, user_profile: UserProfile,
|
2018-05-11 01:39:38 +02:00
|
|
|
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:
|
|
|
|
with mock.patch("zerver.lib.actions.server_initialized", return_value=False):
|
2020-07-26 21:50:16 +02:00
|
|
|
with mock.patch("zerver.lib.actions.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()
|
2020-07-26 21:50:16 +02:00
|
|
|
self.assertEqual(info_logs.output, [
|
|
|
|
'INFO:root:Server not yet initialized. Creating the internal realm first.'
|
|
|
|
])
|
2020-02-12 16:39:12 +01:00
|
|
|
|
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."""
|
2017-05-07 17:21:26 +02:00
|
|
|
self.example_user('hamlet')
|
2017-03-08 12:15:16 +01:00
|
|
|
realm = get_realm('zulip')
|
2020-04-09 21:51:58 +02:00
|
|
|
new_name = 'Zed You Elle Eye Pea'
|
2017-03-21 18:08:40 +01:00
|
|
|
do_set_realm_property(realm, 'name', new_name)
|
2017-03-08 12:15:16 +01:00
|
|
|
self.assertEqual(get_realm(realm.string_id).name, new_name)
|
2017-05-24 02:42:31 +02: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:
|
2017-03-08 12:15:16 +01:00
|
|
|
realm = get_realm('zulip')
|
2020-04-09 21:51:58 +02:00
|
|
|
new_name = 'Puliz'
|
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
|
|
|
events: List[Mapping[str, Any]] = []
|
2017-03-08 12:15:16 +01:00
|
|
|
with tornado_redirected_to_list(events):
|
2017-03-21 18:08:40 +01:00
|
|
|
do_set_realm_property(realm, 'name', new_name)
|
2017-03-08 12:15:16 +01:00
|
|
|
event = events[0]['event']
|
|
|
|
self.assertEqual(event, dict(
|
2017-03-21 18:08:40 +01:00
|
|
|
type='realm',
|
|
|
|
op='update',
|
|
|
|
property='name',
|
|
|
|
value=new_name,
|
|
|
|
))
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_update_realm_description_events(self) -> None:
|
2017-03-21 18:08:40 +01:00
|
|
|
realm = get_realm('zulip')
|
2020-04-09 21:51:58 +02:00
|
|
|
new_description = 'zulip dev group'
|
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
|
|
|
events: List[Mapping[str, Any]] = []
|
2017-03-21 18:08:40 +01:00
|
|
|
with tornado_redirected_to_list(events):
|
|
|
|
do_set_realm_property(realm, 'description', new_description)
|
|
|
|
event = events[0]['event']
|
|
|
|
self.assertEqual(event, dict(
|
|
|
|
type='realm',
|
|
|
|
op='update',
|
|
|
|
property='description',
|
|
|
|
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:
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2020-04-09 21:51:58 +02:00
|
|
|
new_description = 'zulip dev group'
|
2017-03-20 06:49:13 +01:00
|
|
|
data = dict(description=ujson.dumps(new_description))
|
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
|
|
|
events: List[Mapping[str, Any]] = []
|
2017-03-18 20:19:44 +01:00
|
|
|
with tornado_redirected_to_list(events):
|
2017-03-20 06:49:13 +01:00
|
|
|
result = self.client_patch('/json/realm', data)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertEqual(realm.description, new_description)
|
|
|
|
|
2017-03-18 20:19:44 +01:00
|
|
|
event = events[0]['event']
|
|
|
|
self.assertEqual(event, dict(
|
|
|
|
type='realm',
|
|
|
|
op='update',
|
|
|
|
property='description',
|
|
|
|
value=new_description,
|
|
|
|
))
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_realm_description_length(self) -> None:
|
2020-04-09 21:51:58 +02:00
|
|
|
new_description = 'A' * 1001
|
2017-03-18 20:19:44 +01:00
|
|
|
data = dict(description=ujson.dumps(new_description))
|
|
|
|
|
|
|
|
# create an admin user
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2017-03-18 20:19:44 +01:00
|
|
|
|
|
|
|
result = self.client_patch('/json/realm', data)
|
2018-03-17 00:47:55 +01:00
|
|
|
self.assert_json_error(result, 'Organization description is too long.')
|
2017-03-18 20:19:44 +01:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertNotEqual(realm.description, new_description)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_realm_name_length(self) -> None:
|
2020-04-09 21:51:58 +02:00
|
|
|
new_name = 'A' * (Realm.MAX_REALM_NAME_LENGTH + 1)
|
2017-08-23 07:03:19 +02:00
|
|
|
data = dict(name=ujson.dumps(new_name))
|
|
|
|
|
|
|
|
# create an admin user
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2017-08-23 07:03:19 +02:00
|
|
|
|
|
|
|
result = self.client_patch('/json/realm', data)
|
2018-03-17 00:47:55 +01:00
|
|
|
self.assert_json_error(result, 'Organization name is too long.')
|
2017-08-23 07:03:19 +02:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertNotEqual(realm.name, new_name)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_admin_restrictions_for_changing_realm_name(self) -> None:
|
2017-03-08 12:15:16 +01:00
|
|
|
new_name = 'Mice will play while the cat is away'
|
|
|
|
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('othello')
|
2017-03-08 12:15:16 +01:00
|
|
|
|
|
|
|
req = dict(name=ujson.dumps(new_name))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
2018-03-08 01:47:17 +01:00
|
|
|
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:
|
2017-03-13 18:33:49 +01:00
|
|
|
data = {'full_name': 'Sir Hamlet'}
|
2017-05-07 19:39:30 +02:00
|
|
|
user_profile = self.example_user('hamlet')
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login_user(user_profile)
|
2017-03-21 18:08:40 +01:00
|
|
|
do_set_realm_property(user_profile.realm, 'name_changes_disabled', True)
|
2017-07-31 20:44:52 +02:00
|
|
|
url = '/json/settings'
|
|
|
|
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.
|
|
|
|
data = {'full_name': 'New Iago'}
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2018-02-02 16:54:26 +01:00
|
|
|
url = '/json/settings'
|
|
|
|
result = self.client_patch(url, data)
|
|
|
|
self.assert_in_success_response(['"full_name":"New Iago"'], 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()."""
|
2017-05-07 17:21:26 +02:00
|
|
|
self.example_user('hamlet')
|
2017-03-08 12:15:16 +01:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
do_deactivate_realm(realm)
|
2017-05-07 17:21:26 +02:00
|
|
|
user = self.example_user('hamlet')
|
2017-03-08 12:15:16 +01:00
|
|
|
self.assertTrue(user.realm.deactivated)
|
|
|
|
|
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()."""
|
|
|
|
user = get_user_profile_by_email('hamlet@zulip.com')
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
do_change_realm_subdomain(realm, "newzulip")
|
|
|
|
user = get_user_profile_by_email('hamlet@zulip.com')
|
|
|
|
self.assertEqual(user.realm.string_id, "newzulip")
|
|
|
|
# This doesn't use a cache right now, but may later.
|
2019-05-04 04:47:44 +02:00
|
|
|
with self.assertRaises(Realm.DoesNotExist):
|
|
|
|
get_realm("zulip")
|
2018-11-15 23:29:04 +01:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
|
2017-07-01 03:56:40 +02:00
|
|
|
user = self.example_user('hamlet')
|
2017-12-05 03:19:48 +01:00
|
|
|
send_future_email('zerver/emails/followup_day1', user.realm,
|
2018-12-03 23:26:51 +01:00
|
|
|
to_user_ids=[user.id], delay=datetime.timedelta(hours=1))
|
2017-07-02 21:10:41 +02:00
|
|
|
self.assertEqual(ScheduledEmail.objects.count(), 1)
|
2017-07-01 03:56:40 +02:00
|
|
|
do_deactivate_realm(user.realm)
|
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:
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
rendered_description = get_realm_rendered_description(realm)
|
|
|
|
text_description = get_realm_text_description(realm)
|
|
|
|
|
|
|
|
realm.description = 'New Description'
|
|
|
|
realm.save(update_fields=['description'])
|
|
|
|
|
|
|
|
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"""
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
|
|
|
do_deactivate_realm(realm)
|
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
|
|
|
do_deactivate_realm(realm)
|
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
2018-11-12 14:15:49 +01:00
|
|
|
def test_realm_reactivation_link(self) -> None:
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
do_deactivate_realm(realm)
|
|
|
|
self.assertTrue(realm.deactivated)
|
2020-06-14 01:36:12 +02:00
|
|
|
confirmation_url = create_confirmation_link(realm, Confirmation.REALM_REACTIVATION)
|
2018-11-12 14:15:49 +01:00
|
|
|
response = self.client_get(confirmation_url)
|
|
|
|
self.assert_in_success_response(['Your organization has been successfully reactivated'], response)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2019-09-17 14:04:48 +02:00
|
|
|
def test_realm_reactivation_confirmation_object(self) -> None:
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
do_deactivate_realm(realm)
|
|
|
|
self.assertTrue(realm.deactivated)
|
2020-06-14 01:36:12 +02:00
|
|
|
create_confirmation_link(realm, Confirmation.REALM_REACTIVATION)
|
2019-09-17 14:04:48 +02:00
|
|
|
confirmation = Confirmation.objects.last()
|
|
|
|
self.assertEqual(confirmation.content_object, realm)
|
|
|
|
self.assertEqual(confirmation.realm, realm)
|
|
|
|
|
2018-11-12 14:15:49 +01:00
|
|
|
def test_do_send_realm_reactivation_email(self) -> None:
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
do_send_realm_reactivation_email(realm)
|
|
|
|
from django.core.mail import outbox
|
|
|
|
self.assertEqual(len(outbox), 1)
|
2020-06-05 23:26:35 +02:00
|
|
|
self.assertRegex(
|
|
|
|
outbox[0].from_email,
|
|
|
|
fr"^Zulip Account Security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
|
|
|
)
|
2018-11-12 14:15:49 +01:00
|
|
|
self.assertIn('Reactivate your Zulip organization', outbox[0].subject)
|
2018-12-20 21:11:14 +01:00
|
|
|
self.assertIn('Dear former administrators', 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)
|
|
|
|
self.assert_in_success_response(['Your organization has been successfully reactivated'], response)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
|
|
|
def test_realm_reactivation_with_random_link(self) -> None:
|
|
|
|
random_link = "/reactivate/5e89081eb13984e0f3b130bf7a4121d153f1614b"
|
|
|
|
response = self.client_get(random_link)
|
|
|
|
self.assert_in_success_response(['The organization reactivation link has expired or is not valid.'], response)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_change_notifications_stream(self) -> None:
|
2017-06-09 20:50:38 +02:00
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2017-06-09 20:50:38 +02:00
|
|
|
|
|
|
|
disabled_notif_stream_id = -1
|
|
|
|
req = dict(notifications_stream_id = ujson.dumps(disabled_notif_stream_id))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertEqual(realm.notifications_stream, None)
|
|
|
|
|
|
|
|
new_notif_stream_id = 4
|
|
|
|
req = dict(notifications_stream_id = ujson.dumps(new_notif_stream_id))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
2020-07-05 01:39:44 +02:00
|
|
|
assert realm.notifications_stream is not None
|
2017-06-09 20:50:38 +02:00
|
|
|
self.assertEqual(realm.notifications_stream.id, new_notif_stream_id)
|
|
|
|
|
|
|
|
invalid_notif_stream_id = 1234
|
|
|
|
req = dict(notifications_stream_id = ujson.dumps(invalid_notif_stream_id))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, 'Invalid stream id')
|
|
|
|
realm = get_realm('zulip')
|
2020-07-05 01:39:44 +02:00
|
|
|
assert realm.notifications_stream is not None
|
2017-06-09 20:50:38 +02:00
|
|
|
self.assertNotEqual(realm.notifications_stream.id, invalid_notif_stream_id)
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_get_default_notifications_stream(self) -> None:
|
2017-08-24 00:36:29 +02:00
|
|
|
realm = get_realm("zulip")
|
|
|
|
verona = get_stream("verona", realm)
|
2017-09-17 19:53:38 +02:00
|
|
|
realm.notifications_stream_id = verona.id
|
2018-11-15 23:21:22 +01:00
|
|
|
realm.save(update_fields=["notifications_stream"])
|
2017-08-24 00:36:29 +02:00
|
|
|
|
|
|
|
notifications_stream = realm.get_notifications_stream()
|
2020-07-05 01:39:44 +02:00
|
|
|
assert notifications_stream is not None
|
2017-09-17 19:53:38 +02:00
|
|
|
self.assertEqual(notifications_stream.id, verona.id)
|
2017-08-24 00:36:29 +02:00
|
|
|
do_deactivate_stream(notifications_stream)
|
|
|
|
self.assertIsNone(realm.get_notifications_stream())
|
|
|
|
|
2017-10-20 16:55:04 +02:00
|
|
|
def test_change_signup_notifications_stream(self) -> None:
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2017-10-20 16:55:04 +02:00
|
|
|
|
|
|
|
disabled_signup_notifications_stream_id = -1
|
|
|
|
req = dict(signup_notifications_stream_id = ujson.dumps(disabled_signup_notifications_stream_id))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertEqual(realm.signup_notifications_stream, None)
|
|
|
|
|
|
|
|
new_signup_notifications_stream_id = 4
|
|
|
|
req = dict(signup_notifications_stream_id = ujson.dumps(new_signup_notifications_stream_id))
|
2017-12-20 17:58:49 +01:00
|
|
|
|
2017-10-20 16:55:04 +02:00
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
2020-07-05 01:39:44 +02:00
|
|
|
assert realm.signup_notifications_stream is not None
|
2017-10-20 16:55:04 +02:00
|
|
|
self.assertEqual(realm.signup_notifications_stream.id, new_signup_notifications_stream_id)
|
|
|
|
|
|
|
|
invalid_signup_notifications_stream_id = 1234
|
|
|
|
req = dict(signup_notifications_stream_id = ujson.dumps(invalid_signup_notifications_stream_id))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, 'Invalid stream id')
|
|
|
|
realm = get_realm('zulip')
|
2020-07-05 01:39:44 +02:00
|
|
|
assert realm.signup_notifications_stream is not None
|
2017-10-20 16:55:04 +02:00
|
|
|
self.assertNotEqual(realm.signup_notifications_stream.id, invalid_signup_notifications_stream_id)
|
|
|
|
|
2017-10-04 02:01:22 +02:00
|
|
|
def test_get_default_signup_notifications_stream(self) -> None:
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
verona = get_stream("verona", realm)
|
|
|
|
realm.signup_notifications_stream = verona
|
2018-11-15 23:21:22 +01:00
|
|
|
realm.save(update_fields=["signup_notifications_stream"])
|
2017-10-04 02:01:22 +02:00
|
|
|
|
|
|
|
signup_notifications_stream = realm.get_signup_notifications_stream()
|
2020-07-05 01:39:44 +02:00
|
|
|
assert signup_notifications_stream is not None
|
2017-10-04 02:01:22 +02:00
|
|
|
self.assertEqual(signup_notifications_stream, verona)
|
|
|
|
do_deactivate_stream(signup_notifications_stream)
|
|
|
|
self.assertIsNone(realm.get_signup_notifications_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
|
|
|
new_lang = "de"
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertNotEqual(realm.default_language, new_lang)
|
|
|
|
# we need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2017-03-08 12:15:16 +01:00
|
|
|
|
|
|
|
req = dict(default_language=ujson.dumps(new_lang))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertEqual(realm.default_language, new_lang)
|
|
|
|
|
|
|
|
# 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"
|
|
|
|
req = dict(default_language=ujson.dumps(invalid_lang))
|
|
|
|
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}'")
|
2017-03-08 12:15:16 +01:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
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:
|
|
|
|
self.login('desdemona')
|
2018-01-30 14:58:50 +01:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
|
|
|
result = self.client_post('/json/realm/deactivate')
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertTrue(realm.deactivated)
|
|
|
|
|
2020-06-11 00:26:49 +02:00
|
|
|
def test_deactivate_realm_by_non_owner(self) -> None:
|
|
|
|
self.login('iago')
|
2018-01-30 14:58:50 +01:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
|
|
|
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")
|
2018-01-30 14:58:50 +01:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertFalse(realm.deactivated)
|
|
|
|
|
2018-01-29 16:10:54 +01:00
|
|
|
def test_change_bot_creation_policy(self) -> None:
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2018-01-29 16:10:54 +01:00
|
|
|
req = dict(bot_creation_policy = ujson.dumps(Realm.BOT_CREATION_LIMIT_GENERIC_BOTS))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
invalid_add_bot_permission = 4
|
|
|
|
req = dict(bot_creation_policy = ujson.dumps(invalid_add_bot_permission))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
2019-11-04 02:11:56 +01:00
|
|
|
self.assert_json_error(result, 'Invalid bot_creation_policy')
|
2018-01-29 16:10:54 +01:00
|
|
|
|
2018-12-07 00:48:06 +01:00
|
|
|
def test_change_email_address_visibility(self) -> None:
|
|
|
|
# We need an admin user.
|
2018-12-06 23:17:46 +01:00
|
|
|
user_profile = self.example_user("iago")
|
2020-03-07 01:15:34 +01:00
|
|
|
hamlet = self.example_user("hamlet")
|
|
|
|
cordelia = self.example_user("cordelia")
|
|
|
|
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login_user(user_profile)
|
2020-03-07 01:15:34 +01:00
|
|
|
invalid_value = 12
|
2018-12-07 00:48:06 +01:00
|
|
|
req = dict(email_address_visibility = ujson.dumps(invalid_value))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
2019-11-04 02:11:56 +01:00
|
|
|
self.assert_json_error(result, 'Invalid email_address_visibility')
|
2018-12-07 00:48:06 +01:00
|
|
|
|
2020-03-12 14:17:25 +01:00
|
|
|
reset_emails_in_zulip_realm()
|
2018-12-07 00:48:06 +01:00
|
|
|
realm = get_realm("zulip")
|
2020-03-12 14:17:25 +01:00
|
|
|
|
2018-12-07 00:48:06 +01:00
|
|
|
req = dict(email_address_visibility = ujson.dumps(Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.email_address_visibility, Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS)
|
|
|
|
|
2018-12-06 23:17:46 +01:00
|
|
|
edited_user_profile = get_user_profile_by_id(user_profile.id)
|
2020-06-10 06:41:04 +02:00
|
|
|
self.assertEqual(edited_user_profile.email, f"user{edited_user_profile.id}@zulip.testserver")
|
2018-12-06 23:17:46 +01:00
|
|
|
|
2020-03-07 01:15:34 +01:00
|
|
|
# Check normal user cannot access email
|
2020-06-10 06:41:04 +02:00
|
|
|
result = self.api_get(cordelia, f"/api/v1/users/{hamlet.id}")
|
2020-03-07 01:15:34 +01:00
|
|
|
self.assert_json_success(result)
|
2020-03-08 21:13:11 +01:00
|
|
|
self.assertEqual(result.json()['user']['email'],
|
2020-06-10 06:41:04 +02:00
|
|
|
f'user{hamlet.id}@zulip.testserver')
|
2020-03-08 21:13:11 +01:00
|
|
|
self.assertEqual(result.json()['user'].get('delivery_email'), None)
|
2020-03-07 01:15:34 +01:00
|
|
|
|
|
|
|
# Check administrator gets delivery_email with EMAIL_ADDRESS_VISIBILITY_ADMINS
|
2020-06-10 06:41:04 +02:00
|
|
|
result = self.api_get(user_profile, f"/api/v1/users/{hamlet.id}")
|
2020-03-07 01:15:34 +01:00
|
|
|
self.assert_json_success(result)
|
2020-03-08 21:13:11 +01:00
|
|
|
self.assertEqual(result.json()['user']['email'],
|
2020-06-10 06:41:04 +02:00
|
|
|
f'user{hamlet.id}@zulip.testserver')
|
2020-03-08 21:13:11 +01:00
|
|
|
self.assertEqual(result.json()['user'].get('delivery_email'),
|
2020-03-07 01:15:34 +01:00
|
|
|
hamlet.delivery_email)
|
|
|
|
|
|
|
|
req = dict(email_address_visibility = ujson.dumps(Realm.EMAIL_ADDRESS_VISIBILITY_NOBODY))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
realm = get_realm("zulip")
|
|
|
|
self.assertEqual(realm.email_address_visibility, Realm.EMAIL_ADDRESS_VISIBILITY_NOBODY)
|
|
|
|
edited_user_profile = get_user_profile_by_id(user_profile.id)
|
2020-06-10 06:41:04 +02:00
|
|
|
self.assertEqual(edited_user_profile.email, f"user{edited_user_profile.id}@zulip.testserver")
|
2020-03-07 01:15:34 +01:00
|
|
|
|
|
|
|
# Check even administrator doesn't get delivery_email with
|
|
|
|
# EMAIL_ADDRESS_VISIBILITY_NOBODY
|
2020-06-10 06:41:04 +02:00
|
|
|
result = self.api_get(user_profile, f"/api/v1/users/{hamlet.id}")
|
2020-03-07 01:15:34 +01:00
|
|
|
self.assert_json_success(result)
|
2020-03-08 21:13:11 +01:00
|
|
|
self.assertEqual(result.json()['user']['email'],
|
2020-06-10 06:41:04 +02:00
|
|
|
f'user{hamlet.id}@zulip.testserver')
|
2020-03-08 21:13:11 +01:00
|
|
|
self.assertEqual(result.json()['user'].get('delivery_email'), None)
|
2020-03-07 01:15:34 +01:00
|
|
|
|
2019-11-04 02:11:56 +01:00
|
|
|
def test_change_stream_creation_policy(self) -> None:
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2020-04-02 21:53:20 +02:00
|
|
|
req = dict(create_stream_policy = ujson.dumps(Realm.POLICY_ADMINS_ONLY))
|
2019-11-04 02:11:56 +01:00
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
invalid_value = 10
|
|
|
|
req = dict(create_stream_policy = ujson.dumps(invalid_value))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, 'Invalid create_stream_policy')
|
|
|
|
|
|
|
|
def test_change_invite_to_stream_policy(self) -> None:
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2020-04-02 21:53:20 +02:00
|
|
|
req = dict(invite_to_stream_policy = ujson.dumps(Realm.POLICY_ADMINS_ONLY))
|
2019-11-04 02:11:56 +01:00
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
invalid_value = 10
|
|
|
|
req = dict(invite_to_stream_policy = ujson.dumps(invalid_value))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, 'Invalid invite_to_stream_policy')
|
|
|
|
|
|
|
|
def test_user_group_edit_policy(self) -> None:
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2019-11-04 02:11:56 +01:00
|
|
|
req = dict(user_group_edit_policy = ujson.dumps(Realm.USER_GROUP_EDIT_POLICY_ADMINS))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
invalid_value = 10
|
|
|
|
req = dict(user_group_edit_policy = ujson.dumps(invalid_value))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, 'Invalid user_group_edit_policy')
|
|
|
|
|
2020-01-08 01:49:44 +01:00
|
|
|
def test_private_message_policy(self) -> None:
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +01:00
|
|
|
self.login('iago')
|
2020-01-08 01:49:44 +01:00
|
|
|
req = dict(private_message_policy = ujson.dumps(Realm.PRIVATE_MESSAGE_POLICY_DISABLED))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
invalid_value = 10
|
|
|
|
req = dict(private_message_policy = ujson.dumps(invalid_value))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, 'Invalid private_message_policy')
|
|
|
|
|
2019-11-16 19:16:34 +01:00
|
|
|
def test_invalid_integer_attribute_values(self) -> None:
|
|
|
|
|
|
|
|
integer_values = [key for key, value in Realm.property_types.items() if value is int]
|
|
|
|
|
|
|
|
invalid_values = dict(
|
|
|
|
bot_creation_policy=10,
|
|
|
|
create_stream_policy=10,
|
|
|
|
invite_to_stream_policy=10,
|
|
|
|
email_address_visibility=10,
|
|
|
|
message_retention_days=10,
|
2020-04-27 22:41:31 +02:00
|
|
|
video_chat_provider=10,
|
2019-11-16 19:16:34 +01:00
|
|
|
waiting_period_threshold=-10,
|
|
|
|
digest_weekday=10,
|
|
|
|
user_group_edit_policy=10,
|
2020-01-08 01:49:44 +01:00
|
|
|
private_message_policy=10,
|
2020-07-12 21:26:45 +02:00
|
|
|
message_content_delete_limit_seconds=-10,
|
2019-11-16 19:16:34 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
# We need an admin user.
|
2020-03-06 18:40:46 +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:
|
2020-06-10 06:41:04 +02: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}",
|
2019-11-16 19:16:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
req = {val_name: invalid_val}
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
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:
|
2019-05-09 09:54:38 +02:00
|
|
|
self.assertEqual(get_realm('zulip').video_chat_provider, Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'])
|
2020-03-06 18:40:46 +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
|
2019-05-10 10:32:47 +02:00
|
|
|
req = {"video_chat_provider": ujson.dumps(invalid_video_chat_provider_value)}
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result,
|
2019-11-16 19:16:34 +01:00
|
|
|
("Invalid video_chat_provider {}").format(invalid_video_chat_provider_value))
|
2019-05-10 10:32:47 +02:00
|
|
|
|
2020-04-08 00:23:15 +02:00
|
|
|
req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['disabled']['id'])}
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
self.assertEqual(get_realm('zulip').video_chat_provider,
|
|
|
|
Realm.VIDEO_CHAT_PROVIDERS['disabled']['id'])
|
|
|
|
|
2019-05-09 09:54:38 +02:00
|
|
|
req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'])}
|
2018-04-23 14:51:30 +02:00
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
2019-05-09 09:54:38 +02:00
|
|
|
self.assertEqual(get_realm('zulip').video_chat_provider, Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'])
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2020-04-27 22:41:31 +02:00
|
|
|
req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['big_blue_button']['id'])}
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
self.assertEqual(get_realm('zulip').video_chat_provider,
|
|
|
|
Realm.VIDEO_CHAT_PROVIDERS['big_blue_button']['id'])
|
|
|
|
|
2019-05-09 09:54:38 +02:00
|
|
|
req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['zoom']['id'])}
|
2018-12-28 20:45:54 +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):
|
2018-10-17 10:50:59 +02:00
|
|
|
self.assertEqual(do_create_realm('hosted', 'hosted').plan_type, Realm.LIMITED)
|
|
|
|
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):
|
2018-10-17 10:50:59 +02:00
|
|
|
self.assertEqual(do_create_realm('onpremise', 'onpremise').plan_type, Realm.SELF_HOSTED)
|
|
|
|
self.assertEqual(get_realm('onpremise').max_invites, settings.INVITES_DEFAULT_REALM_DAILY_MAX)
|
|
|
|
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
|
|
|
|
2018-10-23 19:25:59 +02:00
|
|
|
def test_change_plan_type(self) -> None:
|
2018-10-17 10:50:59 +02:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
self.assertEqual(realm.plan_type, Realm.SELF_HOSTED)
|
|
|
|
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
|
|
|
|
2018-12-13 07:54:43 +01:00
|
|
|
do_change_plan_type(realm, Realm.STANDARD)
|
2018-10-17 10:50:59 +02:00
|
|
|
realm = get_realm('zulip')
|
2020-02-25 08:17:46 +01:00
|
|
|
self.assertEqual(realm.plan_type, Realm.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)
|
2019-01-14 11:22:59 +01:00
|
|
|
self.assertEqual(realm.upload_quota_gb, Realm.UPLOAD_QUOTA_STANDARD)
|
2018-10-17 10:50:59 +02:00
|
|
|
|
2018-12-13 07:54:43 +01:00
|
|
|
do_change_plan_type(realm, Realm.LIMITED)
|
2018-10-17 10:50:59 +02:00
|
|
|
realm = get_realm('zulip')
|
2020-02-25 08:17:46 +01:00
|
|
|
self.assertEqual(realm.plan_type, Realm.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)
|
2018-10-17 10:50:59 +02:00
|
|
|
|
2018-12-13 07:54:43 +01:00
|
|
|
do_change_plan_type(realm, Realm.STANDARD_FREE)
|
2018-10-17 10:50:59 +02:00
|
|
|
realm = get_realm('zulip')
|
2020-02-25 08:17:46 +01:00
|
|
|
self.assertEqual(realm.plan_type, Realm.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)
|
2019-01-14 11:22:59 +01:00
|
|
|
self.assertEqual(realm.upload_quota_gb, Realm.UPLOAD_QUOTA_STANDARD)
|
2018-10-23 19:25:59 +02:00
|
|
|
|
2020-02-25 08:17:46 +01:00
|
|
|
do_change_plan_type(realm, Realm.LIMITED)
|
|
|
|
|
|
|
|
do_change_plan_type(realm, Realm.SELF_HOSTED)
|
|
|
|
self.assertEqual(realm.plan_type, Realm.SELF_HOSTED)
|
|
|
|
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)
|
|
|
|
|
2020-05-09 19:46:56 +02:00
|
|
|
def test_message_retention_days(self) -> None:
|
|
|
|
self.login('iago')
|
|
|
|
realm = get_realm('zulip')
|
2020-05-19 14:49:48 +02:00
|
|
|
self.assertEqual(realm.plan_type, Realm.SELF_HOSTED)
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2020-06-11 21:16:53 +02:00
|
|
|
req = dict(message_retention_days=ujson.dumps(10))
|
|
|
|
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
|
|
|
|
|
|
|
self.login('desdemona')
|
|
|
|
|
2020-05-09 19:46:56 +02:00
|
|
|
req = dict(message_retention_days=ujson.dumps(0))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': 0")
|
|
|
|
|
|
|
|
req = dict(message_retention_days=ujson.dumps(-10))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(
|
|
|
|
result, "Bad value for 'message_retention_days': -10")
|
|
|
|
|
2020-06-21 11:14:35 +02:00
|
|
|
req = dict(message_retention_days=ujson.dumps('invalid'))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': invalid")
|
|
|
|
|
|
|
|
req = dict(message_retention_days=ujson.dumps(-1))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(result, "Bad value for 'message_retention_days': -1")
|
|
|
|
|
|
|
|
req = dict(message_retention_days=ujson.dumps('forever'))
|
2020-05-09 19:46:56 +02:00
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
req = dict(message_retention_days=ujson.dumps(10))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
|
|
|
|
|
|
|
do_change_plan_type(realm, Realm.LIMITED)
|
|
|
|
req = dict(message_retention_days=ujson.dumps(10))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_error(
|
2020-05-19 14:45:47 +02:00
|
|
|
result, "Available on Zulip Standard. Upgrade to access.")
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2020-05-19 14:49:48 +02:00
|
|
|
do_change_plan_type(realm, Realm.STANDARD)
|
|
|
|
req = dict(message_retention_days=ujson.dumps(10))
|
|
|
|
result = self.client_patch('/json/realm', req)
|
|
|
|
self.assert_json_success(result)
|
2020-05-09 19:46:56 +02:00
|
|
|
|
2017-04-09 00:35:41 +02:00
|
|
|
class RealmAPITest(ZulipTestCase):
|
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def setUp(self) -> None:
|
2019-10-19 20:47:00 +02:00
|
|
|
super().setUp()
|
2020-06-11 21:16:53 +02:00
|
|
|
self.login('desdemona')
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def set_up_db(self, attr: str, value: Any) -> None:
|
2017-04-09 00:35:41 +02:00
|
|
|
realm = get_realm('zulip')
|
|
|
|
setattr(realm, attr, value)
|
2018-11-15 23:21:22 +01:00
|
|
|
realm.save(update_fields=[attr])
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def update_with_api(self, name: str, value: int) -> Realm:
|
2017-04-09 00:35:41 +02:00
|
|
|
result = self.client_patch('/json/realm', {name: ujson.dumps(value)})
|
|
|
|
self.assert_json_success(result)
|
2017-07-11 21:39:43 +02:00
|
|
|
return get_realm('zulip') # refresh data
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2019-05-10 10:06:50 +02:00
|
|
|
def update_with_api_multiple_value(self, data_dict: Dict[str, Any]) -> Realm:
|
|
|
|
result = self.client_patch('/json/realm', data_dict)
|
|
|
|
self.assert_json_success(result)
|
2019-05-09 09:54:38 +02:00
|
|
|
return get_realm('zulip')
|
2019-05-10 10:06:50 +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.
|
|
|
|
"""
|
|
|
|
|
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
|
|
|
bool_tests: List[bool] = [False, True]
|
|
|
|
test_values: Dict[str, Any] = dict(
|
2020-04-09 21:51:58 +02: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],
|
2020-04-09 21:51:58 +02:00
|
|
|
name=['Zulip', 'New Name'],
|
2017-04-09 00:35:41 +02:00
|
|
|
waiting_period_threshold=[10, 20],
|
2020-04-02 21:53:20 +02:00
|
|
|
create_stream_policy=[Realm.POLICY_ADMINS_ONLY,
|
|
|
|
Realm.POLICY_MEMBERS_ONLY,
|
|
|
|
Realm.POLICY_FULL_MEMBERS_ONLY],
|
2019-11-02 17:58:55 +01:00
|
|
|
user_group_edit_policy=[Realm.USER_GROUP_EDIT_POLICY_ADMINS,
|
|
|
|
Realm.USER_GROUP_EDIT_POLICY_MEMBERS],
|
2020-01-08 01:49:44 +01:00
|
|
|
private_message_policy=[Realm.PRIVATE_MESSAGE_POLICY_UNLIMITED,
|
|
|
|
Realm.PRIVATE_MESSAGE_POLICY_DISABLED],
|
2020-04-02 21:53:20 +02:00
|
|
|
invite_to_stream_policy=[Realm.POLICY_ADMINS_ONLY,
|
|
|
|
Realm.POLICY_MEMBERS_ONLY,
|
|
|
|
Realm.POLICY_FULL_MEMBERS_ONLY],
|
2018-01-29 16:10:54 +01:00
|
|
|
bot_creation_policy=[1, 2],
|
2018-12-07 00:48:06 +01:00
|
|
|
email_address_visibility=[Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE,
|
2020-03-07 01:15:34 +01:00
|
|
|
Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS,
|
|
|
|
Realm.EMAIL_ADDRESS_VISIBILITY_NOBODY],
|
2019-05-10 10:06:50 +02:00
|
|
|
video_chat_provider=[
|
|
|
|
dict(
|
2019-05-09 09:54:38 +02:00
|
|
|
video_chat_provider=ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id']),
|
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
|
|
|
),
|
2019-05-10 10:06:50 +02:00
|
|
|
],
|
2020-07-12 21:26:45 +02:00
|
|
|
message_content_delete_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:
|
2020-06-10 06:41:04 +02:00
|
|
|
raise AssertionError(f'No test created for {name}')
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2019-05-10 10:06:50 +02:00
|
|
|
if name == 'video_chat_provider':
|
|
|
|
self.set_up_db(name, vals[0][name])
|
|
|
|
realm = self.update_with_api_multiple_value(vals[0])
|
|
|
|
self.assertEqual(getattr(realm, name), ujson.loads(vals[0][name]))
|
|
|
|
else:
|
|
|
|
self.set_up_db(name, vals[0])
|
|
|
|
realm = self.update_with_api(name, vals[1])
|
|
|
|
self.assertEqual(getattr(realm, name), vals[1])
|
|
|
|
realm = self.update_with_api(name, vals[0])
|
|
|
|
self.assertEqual(getattr(realm, name), vals[0])
|
2017-04-09 00:35:41 +02:00
|
|
|
|
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:
|
2019-02-13 09:04:49 +01:00
|
|
|
with self.subTest(property=prop):
|
|
|
|
self.do_test_realm_update_api(prop)
|
2017-04-09 00:35:41 +02:00
|
|
|
|
2017-11-05 10:51:25 +01:00
|
|
|
def test_update_realm_allow_message_editing(self) -> None:
|
2017-04-09 00:35:41 +02:00
|
|
|
"""Tests updating the realm property 'allow_message_editing'."""
|
|
|
|
self.set_up_db('allow_message_editing', False)
|
|
|
|
self.set_up_db('message_content_edit_limit_seconds', 0)
|
2017-12-03 00:50:48 +01:00
|
|
|
self.set_up_db('allow_community_topic_editing', False)
|
2017-04-09 00:35:41 +02:00
|
|
|
realm = self.update_with_api('allow_message_editing', True)
|
|
|
|
realm = self.update_with_api('message_content_edit_limit_seconds', 100)
|
2017-12-03 00:50:48 +01:00
|
|
|
realm = self.update_with_api('allow_community_topic_editing', True)
|
2017-04-09 00:35:41 +02:00
|
|
|
self.assertEqual(realm.allow_message_editing, True)
|
|
|
|
self.assertEqual(realm.message_content_edit_limit_seconds, 100)
|
2017-12-03 00:50:48 +01:00
|
|
|
self.assertEqual(realm.allow_community_topic_editing, True)
|
2017-04-09 00:35:41 +02:00
|
|
|
realm = self.update_with_api('allow_message_editing', False)
|
|
|
|
self.assertEqual(realm.allow_message_editing, False)
|
|
|
|
self.assertEqual(realm.message_content_edit_limit_seconds, 100)
|
2017-12-03 00:50:48 +01:00
|
|
|
self.assertEqual(realm.allow_community_topic_editing, True)
|
2017-04-09 00:35:41 +02:00
|
|
|
realm = self.update_with_api('message_content_edit_limit_seconds', 200)
|
|
|
|
self.assertEqual(realm.allow_message_editing, False)
|
|
|
|
self.assertEqual(realm.message_content_edit_limit_seconds, 200)
|
2017-12-03 00:50:48 +01:00
|
|
|
self.assertEqual(realm.allow_community_topic_editing, True)
|
|
|
|
realm = self.update_with_api('allow_community_topic_editing', False)
|
|
|
|
self.assertEqual(realm.allow_message_editing, False)
|
|
|
|
self.assertEqual(realm.message_content_edit_limit_seconds, 200)
|
|
|
|
self.assertEqual(realm.allow_community_topic_editing, False)
|
2017-11-26 09:12:10 +01:00
|
|
|
|
|
|
|
def test_update_realm_allow_message_deleting(self) -> None:
|
|
|
|
"""Tests updating the realm property 'allow_message_deleting'."""
|
|
|
|
self.set_up_db('allow_message_deleting', True)
|
|
|
|
self.set_up_db('message_content_delete_limit_seconds', 0)
|
|
|
|
realm = self.update_with_api('allow_message_deleting', False)
|
|
|
|
self.assertEqual(realm.allow_message_deleting, False)
|
|
|
|
self.assertEqual(realm.message_content_delete_limit_seconds, 0)
|
|
|
|
realm = self.update_with_api('allow_message_deleting', True)
|
|
|
|
realm = self.update_with_api('message_content_delete_limit_seconds', 100)
|
|
|
|
self.assertEqual(realm.allow_message_deleting, True)
|
|
|
|
self.assertEqual(realm.message_content_delete_limit_seconds, 100)
|
|
|
|
realm = self.update_with_api('message_content_delete_limit_seconds', 600)
|
|
|
|
self.assertEqual(realm.allow_message_deleting, True)
|
|
|
|
self.assertEqual(realm.message_content_delete_limit_seconds, 600)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
class ScrubRealmTest(ZulipTestCase):
|
|
|
|
def test_scrub_realm(self) -> None:
|
|
|
|
zulip = get_realm("zulip")
|
|
|
|
lear = get_realm("lear")
|
|
|
|
|
|
|
|
iago = self.example_user("iago")
|
|
|
|
othello = self.example_user("othello")
|
|
|
|
|
|
|
|
cordelia = self.lear_user("cordelia")
|
|
|
|
king = self.lear_user("king")
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
Attachment.objects.filter(realm=zulip).delete()
|
2020-06-20 21:58:35 +02:00
|
|
|
Attachment.objects.create(realm=zulip, owner=iago, path_id="a/b/temp1.txt", size=512)
|
|
|
|
Attachment.objects.create(realm=zulip, owner=othello, path_id="a/b/temp2.txt", size=512)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
Attachment.objects.filter(realm=lear).delete()
|
2020-06-20 21:58:35 +02:00
|
|
|
Attachment.objects.create(realm=lear, owner=cordelia, path_id="c/d/temp1.txt", size=512)
|
|
|
|
Attachment.objects.create(realm=lear, owner=king, path_id="c/d/temp2.txt", size=512)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
CustomProfileField.objects.create(realm=lear)
|
|
|
|
|
|
|
|
self.assertEqual(Message.objects.filter(sender__in=[iago, othello]).count(), 10)
|
|
|
|
self.assertEqual(Message.objects.filter(sender__in=[cordelia, king]).count(), 10)
|
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[iago, othello]).count(), 20)
|
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[cordelia, king]).count(), 20)
|
|
|
|
|
|
|
|
self.assertNotEqual(CustomProfileField.objects.filter(realm=zulip).count(), 0)
|
|
|
|
|
2018-10-15 09:59:29 +02:00
|
|
|
with mock.patch('logging.warning'):
|
|
|
|
do_scrub_realm(zulip)
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
self.assertEqual(Message.objects.filter(sender__in=[iago, othello]).count(), 0)
|
|
|
|
self.assertEqual(Message.objects.filter(sender__in=[cordelia, king]).count(), 10)
|
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[iago, othello]).count(), 0)
|
|
|
|
self.assertEqual(UserMessage.objects.filter(user_profile__in=[cordelia, king]).count(), 20)
|
|
|
|
|
|
|
|
self.assertEqual(Attachment.objects.filter(realm=zulip).count(), 0)
|
|
|
|
self.assertEqual(Attachment.objects.filter(realm=lear).count(), 2)
|
|
|
|
|
|
|
|
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:
|
|
|
|
self.assertTrue(re.search("Scrubbed [a-z0-9]{15}", user.full_name))
|
|
|
|
self.assertTrue(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.email))
|
2018-10-15 09:10:37 +02:00
|
|
|
self.assertTrue(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.delivery_email))
|
2018-09-14 13:14:40 +02:00
|
|
|
|
|
|
|
lear_users = UserProfile.objects.filter(realm=lear)
|
|
|
|
for user in lear_users:
|
|
|
|
self.assertIsNone(re.search("Scrubbed [a-z0-9]{15}", user.full_name))
|
|
|
|
self.assertIsNone(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.email))
|
2018-10-15 09:10:37 +02:00
|
|
|
self.assertIsNone(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.delivery_email))
|