From ff1ef097a6dfa49fc1a3d6f169eb4ff605574eb5 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Tue, 12 Nov 2019 16:22:15 -0800 Subject: [PATCH] settings: Extract default settings to a module. This allows mypy to understand their types. Signed-off-by: Anders Kaseorg --- docs/subsystems/settings.md | 14 +- zproject/default_settings.py | 374 ++++++++++++++++++++++++++++++++++ zproject/settings.py | 384 +---------------------------------- 3 files changed, 389 insertions(+), 383 deletions(-) create mode 100644 zproject/default_settings.py diff --git a/docs/subsystems/settings.md b/docs/subsystems/settings.md index cb2ddd71be..11e91ad974 100644 --- a/docs/subsystems/settings.md +++ b/docs/subsystems/settings.md @@ -71,13 +71,13 @@ In a production environment, we have: * `zproject/settings.py` is the main Django settings file for Zulip. It contains all the settings that are constant for all Zulip installations (e.g. configuration for logging, static assets, - middleware, etc.), as well as default values for the settings the - user would set in `/etc/zulip/settings.py` (you can look at the - `DEFAULT_SETTINGS` dictionary to easily review the settings - available). `zproject/settings.py` has a line `from prod_settings + middleware, etc.). It has a line `from prod_settings import *`, which in a prod environment has the effect of importing `/etc/zulip/settings.py` (via a symlink). +* `zproject/default_settings.py` has the default values for the settings the + user would set in `/etc/zulip/settings.py`. + In a development environment, we have `zproject/settings.py`, and additionally: @@ -93,8 +93,10 @@ additionally: When adding a new server setting to Zulip, you will typically add it in two or three places: -* In DEFAULT_SETTINGS in `zproject/settings.py`, with a default value - for production environments. If the settings has a secret key, +* `zproject/default_settings.py`, with a default value + for production environments. + +* If the settings has a secret key, you'll add a `get_secret` call in `zproject/settings.py` (and the user will add the value when they configure the feature). diff --git a/zproject/default_settings.py b/zproject/default_settings.py new file mode 100644 index 0000000000..850f0d7293 --- /dev/null +++ b/zproject/default_settings.py @@ -0,0 +1,374 @@ +from typing import Dict, List, Optional, TYPE_CHECKING + +if TYPE_CHECKING: + from django_auth_ldap.config import LDAPSearch + +from .config import PRODUCTION, DEVELOPMENT, get_secret +if PRODUCTION: + from .prod_settings import EXTERNAL_HOST, ZULIP_ADMINISTRATOR +else: + from .dev_settings import EXTERNAL_HOST, ZULIP_ADMINISTRATOR + +# These settings are intended for the server admin to set. We document them in +# prod_settings_template.py, and in the initial /etc/zulip/settings.py on a new +# install of the Zulip server. + +# Extra HTTP "Host" values to allow (standard ones added in settings.py) +ALLOWED_HOSTS = [] # type: List[str] + +# Basic email settings +NOREPLY_EMAIL_ADDRESS = "noreply@" + EXTERNAL_HOST.split(":")[0] +ADD_TOKENS_TO_NOREPLY_ADDRESS = True +TOKENIZED_NOREPLY_EMAIL_ADDRESS = "noreply-{token}@" + EXTERNAL_HOST.split(":")[0] +PHYSICAL_ADDRESS = '' +FAKE_EMAIL_DOMAIN = EXTERNAL_HOST.split(":")[0] + +# SMTP settings +EMAIL_HOST = None # type: Optional[str] +# Other settings, like EMAIL_HOST_USER, EMAIL_PORT, and EMAIL_USE_TLS, +# we leave up to Django's defaults. + +# LDAP auth +AUTH_LDAP_SERVER_URI = "" +LDAP_EMAIL_ATTR = None # type: Optional[str] +AUTH_LDAP_USERNAME_ATTR = None # type: Optional[str] +AUTH_LDAP_REVERSE_EMAIL_SEARCH = None # type: Optional[LDAPSearch] +# AUTH_LDAP_CONNECTION_OPTIONS: we set ldap.OPT_REFERRALS below if unset. +AUTH_LDAP_CONNECTION_OPTIONS = {} # type: Dict[int, object] +# Disable django-auth-ldap caching, to prevent problems with OU changes. +AUTH_LDAP_CACHE_TIMEOUT = 0 +# Disable syncing user on each login; Using sync_ldap_user_data cron is recommended. +AUTH_LDAP_ALWAYS_UPDATE_USER = False +# Development-only settings for fake LDAP authentication; used to +# support local development of LDAP auth without an LDAP server. +# Detailed docs in zproject/dev_settings.py. +FAKE_LDAP_MODE = None # type: Optional[str] +FAKE_LDAP_NUM_USERS = 8 + +# Social auth; we support providing values for some of these +# settings in zulip-secrets.conf instead of settings.py in development. +SOCIAL_AUTH_GITHUB_KEY = get_secret('social_auth_github_key', development_only=True) +SOCIAL_AUTH_GITHUB_ORG_NAME = None # type: Optional[str] +SOCIAL_AUTH_GITHUB_TEAM_ID = None # type: Optional[str] +SOCIAL_AUTH_SUBDOMAIN = None # type: Optional[str] +SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET = get_secret('azure_oauth2_secret') +SOCIAL_AUTH_GOOGLE_KEY = get_secret('social_auth_google_key', development_only=True) +# SAML: +SOCIAL_AUTH_SAML_SP_ENTITY_ID = None # type: Optional[str] +SOCIAL_AUTH_SAML_SP_PUBLIC_CERT = '' +SOCIAL_AUTH_SAML_SP_PRIVATE_KEY = '' +SOCIAL_AUTH_SAML_ORG_INFO = None # type: Optional[Dict[str, Dict[str, str]]] +SOCIAL_AUTH_SAML_TECHNICAL_CONTACT = None # type: Optional[Dict[str, str]] +SOCIAL_AUTH_SAML_SUPPORT_CONTACT = None # type: Optional[Dict[str, str]] +SOCIAL_AUTH_SAML_ENABLED_IDPS = {} # type: Dict[str, Dict[str, str]] +# Historical name for SOCIAL_AUTH_GITHUB_KEY; still allowed in production. +GOOGLE_OAUTH2_CLIENT_ID = None # type: Optional[str] + +# Other auth +SSO_APPEND_DOMAIN = None # type: Optional[str] + +# Email gateway +EMAIL_GATEWAY_PATTERN = '' +EMAIL_GATEWAY_LOGIN = None # type: Optional[str] +EMAIL_GATEWAY_IMAP_SERVER = None # type: Optional[str] +EMAIL_GATEWAY_IMAP_PORT = None # type: Optional[int] +EMAIL_GATEWAY_IMAP_FOLDER = None # type: Optional[str] +# Not documented for in /etc/zulip/settings.py, since it's rarely needed. +EMAIL_GATEWAY_EXTRA_PATTERN_HACK = None # type: Optional[str] + +# Error reporting +ERROR_REPORTING = True +BROWSER_ERROR_REPORTING = False +LOGGING_SHOW_MODULE = False +LOGGING_SHOW_PID = False +SLOW_QUERY_LOGS_STREAM = None # type: Optional[str] + +# File uploads and avatars +DEFAULT_AVATAR_URI = '/static/images/default-avatar.png' +DEFAULT_LOGO_URI = '/static/images/logo/zulip-org-logo.png' +S3_AVATAR_BUCKET = '' +S3_AUTH_UPLOADS_BUCKET = '' +S3_REGION = '' +LOCAL_UPLOADS_DIR = None # type: Optional[str] +MAX_FILE_UPLOAD_SIZE = 25 + +# Jitsi Meet video call integration; set to None to disable integration. +JITSI_SERVER_URL = 'https://meet.jit.si/' + +# Feedback bot settings +ENABLE_FEEDBACK = PRODUCTION +FEEDBACK_EMAIL = None # type: Optional[str] + +# Max state storage per user +# TODO: Add this to zproject/prod_settings_template.py once stateful bots are fully functional. +USER_STATE_SIZE_LIMIT = 10000000 +# Max size of a single configuration entry of an embedded bot. +BOT_CONFIG_SIZE_LIMIT = 10000 + +# External service configuration +CAMO_URI = '' +MEMCACHED_LOCATION = '127.0.0.1:11211' +RABBITMQ_HOST = '127.0.0.1' +RABBITMQ_USERNAME = 'zulip' +REDIS_HOST = '127.0.0.1' +REDIS_PORT = 6379 +REMOTE_POSTGRES_HOST = '' +REMOTE_POSTGRES_SSLMODE = '' +THUMBOR_URL = '' +THUMBOR_SERVES_CAMO = False +THUMBNAIL_IMAGES = False +SENDFILE_BACKEND = None # type: Optional[str] + +# ToS/Privacy templates +PRIVACY_POLICY = None # type: Optional[str] +TERMS_OF_SERVICE = None # type: Optional[str] + +# Security +ENABLE_FILE_LINKS = False +ENABLE_GRAVATAR = True +INLINE_IMAGE_PREVIEW = True +INLINE_URL_EMBED_PREVIEW = True +NAME_CHANGES_DISABLED = False +AVATAR_CHANGES_DISABLED = False +PASSWORD_MIN_LENGTH = 6 +PASSWORD_MIN_GUESSES = 10000 +PUSH_NOTIFICATION_BOUNCER_URL = None # type: Optional[str] +PUSH_NOTIFICATION_REDACT_CONTENT = False +SUBMIT_USAGE_STATISTICS = True +RATE_LIMITING = True +SEND_LOGIN_EMAILS = True +EMBEDDED_BOTS_ENABLED = False + +# Two Factor Authentication is not yet implementation-complete +TWO_FACTOR_AUTHENTICATION_ENABLED = False + +# This is used to send all hotspots for convenient manual testing +# in development mode. +ALWAYS_SEND_ALL_HOTSPOTS = False + +# In-development search pills feature. +SEARCH_PILLS_ENABLED = False + +# We log emails in development environment for accessing +# them easily through /emails page +DEVELOPMENT_LOG_EMAILS = DEVELOPMENT + + +# These settings are not documented in prod_settings_template.py. +# They should either be documented here, or documented there. +# +# Settings that it makes sense to document here instead of in +# prod_settings_template.py are those that +# * don't make sense to change in production, but rather are intended +# for dev and test environments; or +# * don't make sense to change on a typical production server with +# one or a handful of realms, though they might on an installation +# like zulipchat.com or to work around a problem on another server. + +# The following bots are optional system bots not enabled by +# default. The default ones are defined in INTERNAL_BOTS, below. + +# ERROR_BOT sends Django exceptions to an "errors" stream in the +# system realm. +ERROR_BOT = None # type: Optional[str] +# These are extra bot users for our end-to-end Nagios message +# sending tests. +NAGIOS_STAGING_SEND_BOT = None # type: Optional[str] +NAGIOS_STAGING_RECEIVE_BOT = None # type: Optional[str] +# Feedback bot, messages sent to it are by default emailed to +# FEEDBACK_EMAIL (see above), but can be sent to a stream, +# depending on configuration. +FEEDBACK_BOT = 'feedback@zulip.com' +FEEDBACK_BOT_NAME = 'Zulip Feedback Bot' +FEEDBACK_STREAM = None # type: Optional[str] +# SYSTEM_BOT_REALM would be a constant always set to 'zulip', +# except that it isn't that on zulipchat.com. We will likely do a +# migration and eliminate this parameter in the future. +SYSTEM_BOT_REALM = 'zulipinternal' + +# Structurally, we will probably eventually merge +# analytics into part of the main server, rather +# than a separate app. +EXTRA_INSTALLED_APPS = ['analytics'] + +# Default GOOGLE_CLIENT_ID to the value needed for Android auth to work +GOOGLE_CLIENT_ID = '835904834568-77mtr5mtmpgspj9b051del9i9r5t4g4n.apps.googleusercontent.com' + +# Legacy event logs configuration. Our plans include removing +# log_event entirely in favor of RealmAuditLog, at which point we +# can remove this setting. +EVENT_LOGS_ENABLED = False + +# Used to construct URLs to point to the Zulip server. Since we +# only support HTTPS in production, this is just for development. +EXTERNAL_URI_SCHEME = "https://" + +# Whether anyone can create a new organization on the Zulip server. +OPEN_REALM_CREATION = 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"} + +# Alternate hostnames to serve particular realms on, in addition to +# their usual subdomains. Keys are realm string_ids (aka subdomains), +# and values are alternate hosts. +# The values will also be added to ALLOWED_HOSTS. +REALM_HOSTS = {} # type: Dict[str, str] + +# Whether the server is using the Pgroonga full-text search +# backend. Plan is to turn this on for everyone after further +# testing. +USING_PGROONGA = False + +# How Django should send emails. Set for most contexts below, but +# available for sysadmin override in unusual cases. +EMAIL_BACKEND = None # type: Optional[str] + +# Whether to give admins a warning in the web app that email isn't set up. +# Set below when email isn't configured. +WARN_NO_EMAIL = False + +# Whether to keep extra frontend stack trace data. +# TODO: Investigate whether this should be removed and set one way or other. +SAVE_FRONTEND_STACKTRACES = False + +# If True, disable rate-limiting and other filters on sending error messages +# to admins, and enable logging on the error-reporting itself. Useful +# mainly in development. +DEBUG_ERROR_REPORTING = False + +# Whether to flush memcached after data migrations. Because of +# how we do deployments in a way that avoids reusing memcached, +# this is disabled in production, but we need it in development. +POST_MIGRATION_CACHE_FLUSHING = False + +# Settings for APNS. Only needed on push.zulipchat.com or if +# rebuilding the mobile app with a different push notifications +# server. +APNS_CERT_FILE = None # type: Optional[str] +APNS_SANDBOX = True +APNS_TOPIC = 'org.zulip.Zulip' +ZULIP_IOS_APP_ID = 'org.zulip.Zulip' + +# Max number of "remove notification" FCM/GCM messages to send separately +# in one burst; the rest are batched. Older clients ignore the batched +# portion, so only receive this many removals. Lower values mitigate +# server congestion and client battery use. To batch unconditionally, +# set to 1. +MAX_UNBATCHED_REMOVE_NOTIFICATIONS = 10 + +# Limits related to the size of file uploads; last few in MB. +DATA_UPLOAD_MAX_MEMORY_SIZE = 25 * 1024 * 1024 +MAX_AVATAR_FILE_SIZE = 5 +MAX_ICON_FILE_SIZE = 5 +MAX_LOGO_FILE_SIZE = 5 +MAX_EMOJI_FILE_SIZE = 5 + +# Limits to help prevent spam, in particular by sending invitations. +# +# A non-admin user who's joined an open realm this recently can't invite at all. +INVITES_MIN_USER_AGE_DAYS = 3 +# Default for a realm's `max_invites`; which applies per day, +# and only applies if OPEN_REALM_CREATION is true. +INVITES_DEFAULT_REALM_DAILY_MAX = 100 +# Global rate-limit (list of pairs (days, max)) on invites from new realms. +# Only applies if OPEN_REALM_CREATION is true. +INVITES_NEW_REALM_LIMIT_DAYS = [(1, 100)] +# Definition of a new realm for INVITES_NEW_REALM_LIMIT. +INVITES_NEW_REALM_DAYS = 7 + +# Controls for which links are published in portico footers/headers/etc. +REGISTER_LINK_DISABLED = None # type: Optional[bool] +LOGIN_LINK_DISABLED = False +FIND_TEAM_LINK_DISABLED = True + +# Controls if the server should run certain jobs like deliver_email or +# deliver_scheduled_messages. This setting in long term is meant for +# handling jobs for which we don't have a means of establishing a locking +# mechanism that works with multiple servers running these jobs. +# TODO: We should rename this setting so that it reflects its purpose actively. +EMAIL_DELIVERER_DISABLED = False + +# What domains to treat like the root domain +# "auth" is by default a reserved subdomain for the use by python-social-auth. +ROOT_SUBDOMAIN_ALIASES = ["www", "auth"] +# Whether the root domain is a landing page or can host a realm. +ROOT_DOMAIN_LANDING_PAGE = False + +# If using the Zephyr mirroring supervisord configuration, the +# hostname to connect to in order to transfer credentials from webathena. +PERSONAL_ZMIRROR_SERVER = None # type: Optional[str] + +# When security-relevant links in emails expire. +CONFIRMATION_LINK_DEFAULT_VALIDITY_DAYS = 1 +INVITATION_LINK_VALIDITY_DAYS = 10 +REALM_CREATION_LINK_VALIDITY_DAYS = 7 + +# By default, Zulip uses websockets to send messages. In some +# networks, websockets don't work. One can configure Zulip to +# not use websockets here. +USE_WEBSOCKETS = True + +# Version number for ToS. Change this if you want to force every +# user to click through to re-accept terms of service before using +# Zulip again on the web. +TOS_VERSION = None # type: Optional[str] +# Template to use when bumping TOS_VERSION to explain situation. +FIRST_TIME_TOS_TEMPLATE = None # type: Optional[str] + +# Hostname used for Zulip's statsd logging integration. +STATSD_HOST = '' + +# Configuration for JWT auth. +JWT_AUTH_KEYS = {} # type: Dict[str, str] + +# https://docs.djangoproject.com/en/1.11/ref/settings/#std:setting-SERVER_EMAIL +# Django setting for what from address to use in error emails. +SERVER_EMAIL = ZULIP_ADMINISTRATOR +# Django setting for who receives error emails. +ADMINS = (("Zulip Administrator", ZULIP_ADMINISTRATOR),) + +# From address for welcome emails. +WELCOME_EMAIL_SENDER = None # type: Optional[Dict[str, str]] +# Whether we should use users' own email addresses as the from +# address when sending missed-message emails. Off by default +# because some transactional email providers reject sending such +# emails since they can look like spam. +SEND_MISSED_MESSAGE_EMAILS_AS_USER = False +# Whether to send periodic digests of activity. +SEND_DIGEST_EMAILS = True + +# Used to change the Zulip logo in portico pages. +CUSTOM_LOGO_URL = None # type: Optional[str] + +# Random salt used when deterministically generating passwords in +# development. +INITIAL_PASSWORD_SALT = None # type: Optional[str] + +# Used to control whether certain management commands are run on +# the server. +# TODO: Replace this with a smarter "run on only one server" system. +STAGING = False +# Configuration option for our email/Zulip error reporting. +STAGING_ERROR_NOTIFICATIONS = False + +# How long to wait before presence should treat a user as offline. +# TODO: Figure out why this is different from the corresponding +# value in static/js/presence.js. Also, probably move it out of +# default_settings, since it likely isn't usefully user-configurable. +OFFLINE_THRESHOLD_SECS = 5 * 60 + +# How many days deleted messages data should be kept before being +# permanently deleted. +ARCHIVED_DATA_VACUUMING_DELAY_DAYS = 7 + +# Enables billing pages and plan-based feature gates. If False, all features +# are available to all realms. +BILLING_ENABLED = False + +# Automatically catch-up soft deactivated users when running the +# `soft-deactivate-users` cron. Turn this off if the server has 10Ks of +# users, and you would like to save some disk space. Soft-deactivated +# returning users would still be caught-up normally. +AUTO_CATCH_UP_SOFT_DEACTIVATED_USERS = True diff --git a/zproject/settings.py b/zproject/settings.py index 05826eb9dd..e7257dc97a 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -77,13 +77,6 @@ RUNNING_OPENAPI_CURL_TEST = False # process /etc/boto.cfg. os.environ['BOTO_CONFIG'] = '/etc/zulip/boto.cfg' -# Import variables like secrets from the prod_settings file -# Import prod_settings after determining the deployment/machine type -if PRODUCTION: - from .prod_settings import * -else: - from .dev_settings import * - ######################################################################## # DEFAULT VALUES FOR SETTINGS ######################################################################## @@ -91,377 +84,14 @@ else: # For any settings that are not set in the site-specific configuration file # (/etc/zulip/settings.py in production, or dev_settings.py or test_settings.py # in dev and test), we want to initialize them to sane defaults. +from .default_settings import * -# These settings are intended for the server admin to set. We document them in -# prod_settings_template.py, and in the initial /etc/zulip/settings.py on a new -# install of the Zulip server. -DEFAULT_SETTINGS = { - # Extra HTTP "Host" values to allow (standard ones added below) - 'ALLOWED_HOSTS': [], - - # Basic email settings - 'NOREPLY_EMAIL_ADDRESS': "noreply@" + EXTERNAL_HOST.split(":")[0], - 'ADD_TOKENS_TO_NOREPLY_ADDRESS': True, - 'TOKENIZED_NOREPLY_EMAIL_ADDRESS': "noreply-{token}@" + EXTERNAL_HOST.split(":")[0], - 'PHYSICAL_ADDRESS': '', - 'FAKE_EMAIL_DOMAIN': EXTERNAL_HOST.split(":")[0], - - # SMTP settings - 'EMAIL_HOST': None, - # Other settings, like EMAIL_HOST_USER, EMAIL_PORT, and EMAIL_USE_TLS, - # we leave up to Django's defaults. - - # LDAP auth - 'AUTH_LDAP_SERVER_URI': "", - 'LDAP_EMAIL_ATTR': None, - 'AUTH_LDAP_USERNAME_ATTR': None, - 'AUTH_LDAP_REVERSE_EMAIL_SEARCH': None, - # AUTH_LDAP_CONNECTION_OPTIONS: we set ldap.OPT_REFERRALS below if unset. - 'AUTH_LDAP_CONNECTION_OPTIONS': {}, - # Disable django-auth-ldap caching, to prevent problems with OU changes. - 'AUTH_LDAP_CACHE_TIMEOUT': 0, - # Disable syncing user on each login; Using sync_ldap_user_data cron is recommended. - 'AUTH_LDAP_ALWAYS_UPDATE_USER': False, - # Development-only settings for fake LDAP authentication; used to - # support local development of LDAP auth without an LDAP server. - # Detailed docs in zproject/dev_settings.py. - 'FAKE_LDAP_MODE': None, - 'FAKE_LDAP_NUM_USERS': 8, - - # Social auth; we support providing values for some of these - # settings in zulip-secrets.conf instead of settings.py in development. - 'SOCIAL_AUTH_GITHUB_KEY': get_secret('social_auth_github_key', development_only=True), - 'SOCIAL_AUTH_GITHUB_ORG_NAME': None, - 'SOCIAL_AUTH_GITHUB_TEAM_ID': None, - 'SOCIAL_AUTH_SUBDOMAIN': None, - 'SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET': get_secret('azure_oauth2_secret'), - 'SOCIAL_AUTH_GOOGLE_KEY': get_secret('social_auth_google_key', development_only=True), - # SAML: - 'SOCIAL_AUTH_SAML_SP_ENTITY_ID': None, - 'SOCIAL_AUTH_SAML_SP_PUBLIC_CERT': '', - 'SOCIAL_AUTH_SAML_SP_PRIVATE_KEY': '', - 'SOCIAL_AUTH_SAML_ORG_INFO': None, - 'SOCIAL_AUTH_SAML_TECHNICAL_CONTACT': None, - 'SOCIAL_AUTH_SAML_SUPPORT_CONTACT': None, - 'SOCIAL_AUTH_SAML_ENABLED_IDPS': {}, - # Historical name for SOCIAL_AUTH_GITHUB_KEY; still allowed in production. - 'GOOGLE_OAUTH2_CLIENT_ID': None, - - # Other auth - 'SSO_APPEND_DOMAIN': None, - - # Email gateway - 'EMAIL_GATEWAY_PATTERN': '', - 'EMAIL_GATEWAY_LOGIN': None, - 'EMAIL_GATEWAY_IMAP_SERVER': None, - 'EMAIL_GATEWAY_IMAP_PORT': None, - 'EMAIL_GATEWAY_IMAP_FOLDER': None, - # Not documented for in /etc/zulip/settings.py, since it's rarely needed. - 'EMAIL_GATEWAY_EXTRA_PATTERN_HACK': None, - - # Error reporting - 'ERROR_REPORTING': True, - 'BROWSER_ERROR_REPORTING': False, - 'LOGGING_SHOW_MODULE': False, - 'LOGGING_SHOW_PID': False, - 'SLOW_QUERY_LOGS_STREAM': None, - - # File uploads and avatars - 'DEFAULT_AVATAR_URI': '/static/images/default-avatar.png', - 'DEFAULT_LOGO_URI': '/static/images/logo/zulip-org-logo.png', - 'S3_AVATAR_BUCKET': '', - 'S3_AUTH_UPLOADS_BUCKET': '', - 'S3_REGION': '', - 'LOCAL_UPLOADS_DIR': None, - 'MAX_FILE_UPLOAD_SIZE': 25, - - # Jitsi Meet video call integration; set to None to disable integration. - 'JITSI_SERVER_URL': 'https://meet.jit.si/', - - # Feedback bot settings - 'ENABLE_FEEDBACK': PRODUCTION, - 'FEEDBACK_EMAIL': None, - - # Max state storage per user - # TODO: Add this to zproject/prod_settings_template.py once stateful bots are fully functional. - 'USER_STATE_SIZE_LIMIT': 10000000, - # Max size of a single configuration entry of an embedded bot. - 'BOT_CONFIG_SIZE_LIMIT': 10000, - - # External service configuration - 'CAMO_URI': '', - 'MEMCACHED_LOCATION': '127.0.0.1:11211', - 'RABBITMQ_HOST': '127.0.0.1', - 'RABBITMQ_USERNAME': 'zulip', - 'REDIS_HOST': '127.0.0.1', - 'REDIS_PORT': 6379, - 'REMOTE_POSTGRES_HOST': '', - 'REMOTE_POSTGRES_SSLMODE': '', - 'THUMBOR_URL': '', - 'THUMBOR_SERVES_CAMO': False, - 'THUMBNAIL_IMAGES': False, - 'SENDFILE_BACKEND': None, - - # ToS/Privacy templates - 'PRIVACY_POLICY': None, - 'TERMS_OF_SERVICE': None, - - # Security - 'ENABLE_FILE_LINKS': False, - 'ENABLE_GRAVATAR': True, - 'INLINE_IMAGE_PREVIEW': True, - 'INLINE_URL_EMBED_PREVIEW': True, - 'NAME_CHANGES_DISABLED': False, - 'AVATAR_CHANGES_DISABLED': False, - 'PASSWORD_MIN_LENGTH': 6, - 'PASSWORD_MIN_GUESSES': 10000, - 'PUSH_NOTIFICATION_BOUNCER_URL': None, - 'PUSH_NOTIFICATION_REDACT_CONTENT': False, - 'SUBMIT_USAGE_STATISTICS': True, - 'RATE_LIMITING': True, - 'SEND_LOGIN_EMAILS': True, - 'EMBEDDED_BOTS_ENABLED': False, - - # Two Factor Authentication is not yet implementation-complete - 'TWO_FACTOR_AUTHENTICATION_ENABLED': False, - - # This is used to send all hotspots for convenient manual testing - # in development mode. - 'ALWAYS_SEND_ALL_HOTSPOTS': False, - - # In-development search pills feature. - 'SEARCH_PILLS_ENABLED': False, - - # We log emails in development environment for accessing - # them easily through /emails page - 'DEVELOPMENT_LOG_EMAILS': DEVELOPMENT, -} - -# These settings are not documented in prod_settings_template.py. -# They should either be documented here, or documented there. -# -# Settings that it makes sense to document here instead of in -# prod_settings_template.py are those that -# * don't make sense to change in production, but rather are intended -# for dev and test environments; or -# * don't make sense to change on a typical production server with -# one or a handful of realms, though they might on an installation -# like zulipchat.com or to work around a problem on another server. -DEFAULT_SETTINGS.update({ - - # The following bots are optional system bots not enabled by - # default. The default ones are defined in INTERNAL_BOTS, below. - - # ERROR_BOT sends Django exceptions to an "errors" stream in the - # system realm. - 'ERROR_BOT': None, - # These are extra bot users for our end-to-end Nagios message - # sending tests. - 'NAGIOS_STAGING_SEND_BOT': None, - 'NAGIOS_STAGING_RECEIVE_BOT': None, - # Feedback bot, messages sent to it are by default emailed to - # FEEDBACK_EMAIL (see above), but can be sent to a stream, - # depending on configuration. - 'FEEDBACK_BOT': 'feedback@zulip.com', - 'FEEDBACK_BOT_NAME': 'Zulip Feedback Bot', - 'FEEDBACK_STREAM': None, - # SYSTEM_BOT_REALM would be a constant always set to 'zulip', - # except that it isn't that on zulipchat.com. We will likely do a - # migration and eliminate this parameter in the future. - 'SYSTEM_BOT_REALM': 'zulipinternal', - - # Structurally, we will probably eventually merge - # analytics into part of the main server, rather - # than a separate app. - 'EXTRA_INSTALLED_APPS': ['analytics'], - - # Default GOOGLE_CLIENT_ID to the value needed for Android auth to work - 'GOOGLE_CLIENT_ID': '835904834568-77mtr5mtmpgspj9b051del9i9r5t4g4n.apps.googleusercontent.com', - - # Legacy event logs configuration. Our plans include removing - # log_event entirely in favor of RealmAuditLog, at which point we - # can remove this setting. - 'EVENT_LOGS_ENABLED': False, - - # Used to construct URLs to point to the Zulip server. Since we - # only support HTTPS in production, this is just for development. - 'EXTERNAL_URI_SCHEME': "https://", - - # Whether anyone can create a new organization on the Zulip server. - 'OPEN_REALM_CREATION': 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"}, - - # Alternate hostnames to serve particular realms on, in addition to - # their usual subdomains. Keys are realm string_ids (aka subdomains), - # and values are alternate hosts. - # The values will also be added to ALLOWED_HOSTS. - 'REALM_HOSTS': {}, - - # Whether the server is using the Pgroonga full-text search - # backend. Plan is to turn this on for everyone after further - # testing. - 'USING_PGROONGA': False, - - # How Django should send emails. Set for most contexts below, but - # available for sysadmin override in unusual cases. - 'EMAIL_BACKEND': None, - - # Whether to give admins a warning in the web app that email isn't set up. - # Set below when email isn't configured. - 'WARN_NO_EMAIL': False, - - # Whether to keep extra frontend stack trace data. - # TODO: Investigate whether this should be removed and set one way or other. - 'SAVE_FRONTEND_STACKTRACES': False, - - # If True, disable rate-limiting and other filters on sending error messages - # to admins, and enable logging on the error-reporting itself. Useful - # mainly in development. - 'DEBUG_ERROR_REPORTING': False, - - # Whether to flush memcached after data migrations. Because of - # how we do deployments in a way that avoids reusing memcached, - # this is disabled in production, but we need it in development. - 'POST_MIGRATION_CACHE_FLUSHING': False, - - # Settings for APNS. Only needed on push.zulipchat.com or if - # rebuilding the mobile app with a different push notifications - # server. - 'APNS_CERT_FILE': None, - 'APNS_SANDBOX': True, - 'APNS_TOPIC': 'org.zulip.Zulip', - 'ZULIP_IOS_APP_ID': 'org.zulip.Zulip', - - # Max number of "remove notification" FCM/GCM messages to send separately - # in one burst; the rest are batched. Older clients ignore the batched - # portion, so only receive this many removals. Lower values mitigate - # server congestion and client battery use. To batch unconditionally, - # set to 1. - 'MAX_UNBATCHED_REMOVE_NOTIFICATIONS': 10, - - # Limits related to the size of file uploads; last few in MB. - 'DATA_UPLOAD_MAX_MEMORY_SIZE': 25 * 1024 * 1024, - 'MAX_AVATAR_FILE_SIZE': 5, - 'MAX_ICON_FILE_SIZE': 5, - 'MAX_LOGO_FILE_SIZE': 5, - 'MAX_EMOJI_FILE_SIZE': 5, - - # Limits to help prevent spam, in particular by sending invitations. - # - # A non-admin user who's joined an open realm this recently can't invite at all. - 'INVITES_MIN_USER_AGE_DAYS': 3, - # Default for a realm's `max_invites`; which applies per day, - # and only applies if OPEN_REALM_CREATION is true. - 'INVITES_DEFAULT_REALM_DAILY_MAX': 100, - # Global rate-limit (list of pairs (days, max)) on invites from new realms. - # Only applies if OPEN_REALM_CREATION is true. - 'INVITES_NEW_REALM_LIMIT_DAYS': [(1, 100)], - # Definition of a new realm for INVITES_NEW_REALM_LIMIT. - 'INVITES_NEW_REALM_DAYS': 7, - - # Controls for which links are published in portico footers/headers/etc. - 'REGISTER_LINK_DISABLED': None, - 'LOGIN_LINK_DISABLED': False, - 'FIND_TEAM_LINK_DISABLED': True, - - # Controls if the server should run certain jobs like deliver_email or - # deliver_scheduled_messages. This setting in long term is meant for - # handling jobs for which we don't have a means of establishing a locking - # mechanism that works with multiple servers running these jobs. - # TODO: We should rename this setting so that it reflects its purpose actively. - 'EMAIL_DELIVERER_DISABLED': False, - - # What domains to treat like the root domain - # "auth" is by default a reserved subdomain for the use by python-social-auth. - 'ROOT_SUBDOMAIN_ALIASES': ["www", "auth"], - # Whether the root domain is a landing page or can host a realm. - 'ROOT_DOMAIN_LANDING_PAGE': False, - - # If using the Zephyr mirroring supervisord configuration, the - # hostname to connect to in order to transfer credentials from webathena. - 'PERSONAL_ZMIRROR_SERVER': None, - - # When security-relevant links in emails expire. - 'CONFIRMATION_LINK_DEFAULT_VALIDITY_DAYS': 1, - 'INVITATION_LINK_VALIDITY_DAYS': 10, - 'REALM_CREATION_LINK_VALIDITY_DAYS': 7, - - # By default, Zulip uses websockets to send messages. In some - # networks, websockets don't work. One can configure Zulip to - # not use websockets here. - 'USE_WEBSOCKETS': True, - - # Version number for ToS. Change this if you want to force every - # user to click through to re-accept terms of service before using - # Zulip again on the web. - 'TOS_VERSION': None, - # Template to use when bumping TOS_VERSION to explain situation. - 'FIRST_TIME_TOS_TEMPLATE': None, - - # Hostname used for Zulip's statsd logging integration. - 'STATSD_HOST': '', - - # Configuration for JWT auth. - 'JWT_AUTH_KEYS': {}, - - # https://docs.djangoproject.com/en/1.11/ref/settings/#std:setting-SERVER_EMAIL - # Django setting for what from address to use in error emails. - 'SERVER_EMAIL': ZULIP_ADMINISTRATOR, - # Django setting for who receives error emails. - 'ADMINS': (("Zulip Administrator", ZULIP_ADMINISTRATOR),), - - # From address for welcome emails. - 'WELCOME_EMAIL_SENDER': None, - # Whether we should use users' own email addresses as the from - # address when sending missed-message emails. Off by default - # because some transactional email providers reject sending such - # emails since they can look like spam. - 'SEND_MISSED_MESSAGE_EMAILS_AS_USER': False, - # Whether to send periodic digests of activity. - 'SEND_DIGEST_EMAILS': True, - - # Used to change the Zulip logo in portico pages. - 'CUSTOM_LOGO_URL': None, - - # Random salt used when deterministically generating passwords in - # development. - 'INITIAL_PASSWORD_SALT': None, - - # Used to control whether certain management commands are run on - # the server. - # TODO: Replace this with a smarter "run on only one server" system. - 'STAGING': False, - # Configuration option for our email/Zulip error reporting. - 'STAGING_ERROR_NOTIFICATIONS': False, - - # How long to wait before presence should treat a user as offline. - # TODO: Figure out why this is different from the corresponding - # value in static/js/presence.js. Also, probably move it out of - # DEFAULT_SETTINGS, since it likely isn't usefully user-configurable. - 'OFFLINE_THRESHOLD_SECS': 5 * 60, - - # How many days deleted messages data should be kept before being - # permanently deleted. - 'ARCHIVED_DATA_VACUUMING_DELAY_DAYS': 7, - - # Enables billing pages and plan-based feature gates. If False, all features - # are available to all realms. - 'BILLING_ENABLED': False, - - # Automatically catch-up soft deactivated users when running the - # `soft-deactivate-users` cron. Turn this off if the server has 10Ks of - # users, and you would like to save some disk space. Soft-deactivated - # returning users would still be caught-up normally. - 'AUTO_CATCH_UP_SOFT_DEACTIVATED_USERS': True, -}) - - -for setting_name, setting_val in DEFAULT_SETTINGS.items(): - if setting_name not in vars(): - vars()[setting_name] = setting_val +# Import variables like secrets from the prod_settings file +# Import prod_settings after determining the deployment/machine type +if PRODUCTION: + from .prod_settings import * +else: + from .dev_settings import * # These are the settings that we will check that the user has filled in for # production deployments before starting the app. It consists of a series