settings: Add web_public_streams_enabled server setting.

This new setting both serves as a guard to allow us to merge API
support for web public streams to main before we're ready for this
feature to be available on Zulip Cloud, and also long term will
protect self-hosted servers from accidentally enabling web-public
streams (which could be a scary possibility for the administrators of
a corporate Zulip server).
This commit is contained in:
Tim Abbott 2021-09-21 10:49:12 -07:00
parent 8c50a08066
commit 8fe61674d4
4 changed files with 37 additions and 4 deletions

View File

@ -852,15 +852,27 @@ class Realm(models.Model):
def presence_disabled(self) -> bool:
return self.is_zephyr_mirror_realm
def web_public_streams_enabled(self) -> bool:
if not settings.WEB_PUBLIC_STREAMS_ENABLED:
# To help protect against accidentally web-public streams in
# self-hosted servers, we require the feature to be enabled at
# the server level before it is available to users.
return False
if self.plan_type == Realm.LIMITED:
# In Zulip Cloud, we also require a paid or sponsored
# plan, to protect against the spam/abuse attacks that
# target every open Internet service that can host files.
return False
return True
def has_web_public_streams(self) -> bool:
"""
If any of the streams in the realm is web
public, then the realm is web public.
"""
if self.plan_type == Realm.LIMITED:
# We don't enable web public streams feature
# for realms on LIMITED plan to avoid spamming
# behaviour.
if not self.web_public_streams_enabled():
return False
return Stream.objects.filter(realm=self, is_web_public=True).exists()

View File

@ -741,23 +741,40 @@ class RealmTest(ZulipTestCase):
rome = Stream.objects.get(name="Rome")
self.assertEqual(rome.is_web_public, True)
self.assertEqual(realm.has_web_public_streams(), True)
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)
# 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)
self.assertEqual(realm.web_public_streams_enabled(), True)
self.assertEqual(realm.has_web_public_streams(), False)
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
self.assertEqual(realm.web_public_streams_enabled(), False)
self.assertEqual(realm.has_web_public_streams(), False)
# 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)
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)
realm.plan_type = Realm.LIMITED
realm.save()
self.assertEqual(Stream.objects.filter(realm=realm, is_web_public=True).count(), 1)
self.assertEqual(realm.web_public_streams_enabled(), False)
self.assertEqual(realm.has_web_public_streams(), False)
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
self.assertEqual(realm.web_public_streams_enabled(), False)
self.assertEqual(realm.has_web_public_streams(), False)
class RealmAPITest(ZulipTestCase):

View File

@ -262,6 +262,9 @@ EXTERNAL_URI_SCHEME = "https://"
# Whether anyone can create a new organization on the Zulip server.
OPEN_REALM_CREATION = False
# Whether it's possible to create web-public streams on this server.
WEB_PUBLIC_STREAMS_ENABLED = False
# Setting for where the system bot users are. Likely has no
# purpose now that the REALMS_HAVE_SUBDOMAINS migration is finished.
SYSTEM_ONLY_REALMS = {"zulip"}

View File

@ -74,6 +74,7 @@ CAMO_URI = ""
TORNADO_PORTS = [9993]
OPEN_REALM_CREATION = True
WEB_PUBLIC_STREAMS_ENABLED = True
INVITES_MIN_USER_AGE_DAYS = 0
EMBEDDED_BOTS_ENABLED = True