Skip to content
Snippets Groups Projects
Unverified Commit 77269633 authored by Fredrik Jonsson's avatar Fredrik Jonsson Committed by GitHub
Browse files

Merge pull request #2701 from HyphaApp/enhancement/gh-2471-environ

Use environs package to parse  .env variables.
parents 0d7257a4 e6b407aa
No related branches found
No related tags found
No related merge requests found
...@@ -6,63 +6,43 @@ Django settings for hypha project. ...@@ -6,63 +6,43 @@ Django settings for hypha project.
import os import os
import dj_database_url import dj_database_url
from environs import Env
env = os.environ.copy() env = Env()
env.read_env()
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_DIR = os.path.dirname(PROJECT_DIR) BASE_DIR = os.path.dirname(PROJECT_DIR)
APP_NAME = env.get('APP_NAME', 'hypha') APP_NAME = env.str('APP_NAME', 'hypha')
DEBUG = False DEBUG = False
# SECRET_KEY is required
SECRET_KEY = env.str('SECRET_KEY', None)
if 'SECRET_KEY' in env: ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', [])
SECRET_KEY = env['SECRET_KEY']
if 'ALLOWED_HOSTS' in env:
ALLOWED_HOSTS = env['ALLOWED_HOSTS'].split(',')
# Organisation name and e-mail address, used in e-mail templates etc. # Organisation name and e-mail address, used in e-mail templates etc.
ORG_LONG_NAME = env.str('ORG_LONG_NAME', 'Acme Corporation')
ORG_LONG_NAME = env.get('ORG_LONG_NAME', 'Acme Corporation') ORG_SHORT_NAME = env.str('ORG_SHORT_NAME', 'ACME')
ORG_SHORT_NAME = env.get('ORG_SHORT_NAME', 'ACME') ORG_EMAIL = env.str('ORG_EMAIL', 'info@example.org')
ORG_EMAIL = env.get('ORG_EMAIL', 'info@example.org') ORG_GUIDE_URL = env.url('ORG_GUIDE_URL', 'https://guide.example.org/')
ORG_GUIDE_URL = env.get('ORG_GUIDE_URL', 'https://guide.example.org/')
# Email settings # Email settings
if 'EMAIL_HOST' in env: EMAIL_HOST = env.str('EMAIL_HOST', None)
EMAIL_HOST = env['EMAIL_HOST'] EMAIL_PORT = env.int('EMAIL_PORT', None)
EMAIL_HOST_USER = env.str('EMAIL_HOST_USER', None)
if 'EMAIL_PORT' in env: EMAIL_HOST_PASSWORD = env.str('EMAIL_HOST_PASSWORD', None)
try: EMAIL_USE_TLS = env.bool('EMAIL_USE_TLS', False)
EMAIL_PORT = int(env['EMAIL_PORT']) EMAIL_USE_SSL = env.bool('EMAIL_USE_SSL', False)
except ValueError: EMAIL_SUBJECT_PREFIX = env.str('EMAIL_SUBJECT_PREFIX', None)
pass SERVER_EMAIL = DEFAULT_FROM_EMAIL = env.str('SERVER_EMAIL', None)
if 'EMAIL_HOST_USER' in env:
EMAIL_HOST_USER = env['EMAIL_HOST_USER']
if 'EMAIL_HOST_PASSWORD' in env:
EMAIL_HOST_PASSWORD = env['EMAIL_HOST_PASSWORD']
if env.get('EMAIL_USE_TLS', 'false').lower().strip() == 'true':
EMAIL_USE_TLS = True
if env.get('EMAIL_USE_SSL', 'false').lower().strip() == 'true':
EMAIL_USE_SSL = True
if 'EMAIL_SUBJECT_PREFIX' in env:
EMAIL_SUBJECT_PREFIX = env['EMAIL_SUBJECT_PREFIX']
if 'SERVER_EMAIL' in env:
SERVER_EMAIL = DEFAULT_FROM_EMAIL = env['SERVER_EMAIL']
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'scout_apm.django', 'scout_apm.django',
...@@ -206,30 +186,22 @@ FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' ...@@ -206,30 +186,22 @@ FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
WSGI_APPLICATION = 'hypha.wsgi.application' WSGI_APPLICATION = 'hypha.wsgi.application'
# Database # Database
# https://docs.djangoproject.com/en/stable/ref/settings/#databases # https://docs.djangoproject.com/en/stable/ref/settings/#databases
DATABASES = { DATABASES = {
'default': dj_database_url.config( 'default': dj_database_url.config(
conn_max_age=600, conn_max_age=600,
default=f"postgres:///{APP_NAME}" default=f'postgres:///{APP_NAME}'
) )
} }
# Cache # Cache
# Set max-age header. # Set max-age header.
try: CACHE_CONTROL_MAX_AGE = env.int('CACHE_CONTROL_MAX_AGE', 3600)
CACHE_CONTROL_MAX_AGE = int(env.get('CACHE_CONTROL_MAX_AGE', 3600))
except ValueError:
CACHE_CONTROL_MAX_AGE = 3600
# Set s-max-age header that is used by reverse proxy/front end cache. # Set s-max-age header that is used by reverse proxy/front end cache.
try: CACHE_CONTROL_S_MAXAGE = env.int('CACHE_CONTROL_S_MAXAGE', 3600)
CACHE_CONTROL_S_MAXAGE = int(env.get('CACHE_CONTROL_S_MAXAGE', 3600))
except ValueError:
CACHE_CONTROL_S_MAXAGE = 3600
# Set wagtail cache timeout (automatic cache refresh). # Set wagtail cache timeout (automatic cache refresh).
WAGTAIL_CACHE_TIMEOUT = CACHE_CONTROL_MAX_AGE WAGTAIL_CACHE_TIMEOUT = CACHE_CONTROL_MAX_AGE
...@@ -237,15 +209,15 @@ WAGTAIL_CACHE_TIMEOUT = CACHE_CONTROL_MAX_AGE ...@@ -237,15 +209,15 @@ WAGTAIL_CACHE_TIMEOUT = CACHE_CONTROL_MAX_AGE
# Set feed cache timeout (automatic cache refresh). # Set feed cache timeout (automatic cache refresh).
FEED_CACHE_TIMEOUT = 600 FEED_CACHE_TIMEOUT = 600
if 'REDIS_URL' in env: if env.str('REDIS_URL', None):
CACHES = { CACHES = {
'default': { 'default': {
'BACKEND': 'django_redis.cache.RedisCache', 'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': env['REDIS_URL'], 'LOCATION': env.dj_cache_url('REDIS_URL'),
}, },
'wagtailcache': { 'wagtailcache': {
'BACKEND': 'wagtailcache.compat_backends.django_redis.RedisCache', 'BACKEND': 'wagtailcache.compat_backends.django_redis.RedisCache',
'LOCATION': env['REDIS_URL'], 'LOCATION': env.dj_cache_url('REDIS_URL'),
'KEY_PREFIX': 'wagtailcache', 'KEY_PREFIX': 'wagtailcache',
'TIMEOUT': WAGTAIL_CACHE_TIMEOUT, 'TIMEOUT': WAGTAIL_CACHE_TIMEOUT,
} }
...@@ -279,19 +251,18 @@ WAGTAIL_CACHE_BACKEND = 'wagtailcache' ...@@ -279,19 +251,18 @@ WAGTAIL_CACHE_BACKEND = 'wagtailcache'
# Cloudflare cache invalidation. # Cloudflare cache invalidation.
# See https://docs.wagtail.io/en/v2.8/reference/contrib/frontendcache.html # See https://docs.wagtail.io/en/v2.8/reference/contrib/frontendcache.html
if 'CLOUDFLARE_BEARER_TOKEN' in env and 'CLOUDFLARE_API_ZONEID' in env: if env.str('CLOUDFLARE_BEARER_TOKEN', None) and env.str('CLOUDFLARE_API_ZONEID'):
INSTALLED_APPS += ('wagtail.contrib.frontend_cache', ) # noqa INSTALLED_APPS += ('wagtail.contrib.frontend_cache', ) # noqa
WAGTAILFRONTENDCACHE = { WAGTAILFRONTENDCACHE = {
'cloudflare': { 'cloudflare': {
'BACKEND': 'wagtail.contrib.frontend_cache.backends.CloudflareBackend', 'BACKEND': 'wagtail.contrib.frontend_cache.backends.CloudflareBackend',
'BEARER_TOKEN': env['CLOUDFLARE_BEARER_TOKEN'], 'BEARER_TOKEN': env.str('CLOUDFLARE_BEARER_TOKEN'),
'ZONEID': env['CLOUDFLARE_API_ZONEID'], 'ZONEID': env.str('CLOUDFLARE_API_ZONEID'),
}, },
} }
# Search # Search
WAGTAILSEARCH_BACKENDS = { WAGTAILSEARCH_BACKENDS = {
'default': { 'default': {
'BACKEND': 'wagtail.contrib.postgres_search.backend', 'BACKEND': 'wagtail.contrib.postgres_search.backend',
...@@ -301,7 +272,6 @@ WAGTAILSEARCH_BACKENDS = { ...@@ -301,7 +272,6 @@ WAGTAILSEARCH_BACKENDS = {
# Password validation # Password validation
# https://docs.djangoproject.com/en/stable/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/stable/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
...@@ -318,38 +288,27 @@ AUTH_PASSWORD_VALIDATORS = [ ...@@ -318,38 +288,27 @@ AUTH_PASSWORD_VALIDATORS = [
] ]
# Number of days that password reset and account activation links are valid (default 3). # Number of days that password reset and account activation links are valid (default 3).
if 'PASSWORD_RESET_TIMEOUT_DAYS' in env: PASSWORD_RESET_TIMEOUT_DAYS = env.int('PASSWORD_RESET_TIMEOUT_DAYS', 3)
try:
PASSWORD_RESET_TIMEOUT_DAYS = int(env['PASSWORD_RESET_TIMEOUT_DAYS'])
except ValueError:
pass
# Seconds to enter password on password page while email change/2FA change (default 120). # Seconds to enter password on password page while email change/2FA change (default 120).
PASSWORD_PAGE_TIMEOUT_SECONDS = int(env.get('PASSWORD_PAGE_TIMEOUT_SECONDS', 120)) PASSWORD_PAGE_TIMEOUT_SECONDS = env.int('PASSWORD_PAGE_TIMEOUT_SECONDS', 120)
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/stable/topics/i18n/ # https://docs.djangoproject.com/en/stable/topics/i18n/
# Language code in standard language id format: en, en-gb, en-us # Language code in standard language id format: en, en-gb, en-us
# The corrosponding locale dir is named: en, en_GB, en_US # The corrosponding locale dir is named: en, en_GB, en_US
LANGUAGE_CODE = env.get('LANGUAGE_CODE', 'en') LANGUAGE_CODE = env.str('LANGUAGE_CODE', 'en')
CURRENCY_SYMBOL = env.get('CURRENCY_SYMBOL', '$') CURRENCY_SYMBOL = env.str('CURRENCY_SYMBOL', '$')
TIME_ZONE = 'UTC' TIME_ZONE = 'UTC'
USE_I18N = True USE_I18N = True
USE_L10N = False USE_L10N = False
USE_TZ = True USE_TZ = True
DATE_FORMAT = 'N j, Y' DATE_FORMAT = 'N j, Y'
DATETIME_FORMAT = 'N j, Y, H:i' DATETIME_FORMAT = 'N j, Y, H:i'
SHORT_DATE_FORMAT = 'Y-m-d' SHORT_DATE_FORMAT = 'Y-m-d'
SHORT_DATETIME_FORMAT = 'Y-m-d H:i' SHORT_DATETIME_FORMAT = 'Y-m-d H:i'
DATETIME_INPUT_FORMATS = [ DATETIME_INPUT_FORMATS = [
...@@ -372,7 +331,6 @@ LOCALE_PATHS = ( ...@@ -372,7 +331,6 @@ LOCALE_PATHS = (
PROJECT_DIR + '/locale', PROJECT_DIR + '/locale',
) )
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/stable/howto/static-files/ # https://docs.djangoproject.com/en/stable/howto/static-files/
...@@ -383,12 +341,11 @@ STATICFILES_DIRS = [ ...@@ -383,12 +341,11 @@ STATICFILES_DIRS = [
os.path.join(PROJECT_DIR, '../public'), os.path.join(PROJECT_DIR, '../public'),
] ]
STATIC_ROOT = env.get('STATIC_DIR', os.path.join(BASE_DIR, 'static')) STATIC_ROOT = env.str('STATIC_DIR', os.path.join(BASE_DIR, 'static'))
STATIC_URL = env.get('STATIC_URL', '/static/') STATIC_URL = env.str('STATIC_URL', '/static/')
MEDIA_ROOT = env.get('MEDIA_DIR', os.path.join(BASE_DIR, 'media'))
MEDIA_URL = env.get('MEDIA_URL', '/media/')
MEDIA_ROOT = env.str('MEDIA_DIR', os.path.join(BASE_DIR, 'media'))
MEDIA_URL = env.str('MEDIA_URL', '/media/')
AUTH_USER_MODEL = 'users.User' AUTH_USER_MODEL = 'users.User'
...@@ -407,7 +364,6 @@ AUTHENTICATION_BACKENDS = ( ...@@ -407,7 +364,6 @@ AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', 'django.contrib.auth.backends.ModelBackend',
) )
# Logging # Logging
LOGGING = { LOGGING = {
'version': 1, 'version': 1,
...@@ -457,9 +413,7 @@ LOGGING = { ...@@ -457,9 +413,7 @@ LOGGING = {
# Wagtail settings # Wagtail settings
WAGTAIL_FRONTEND_LOGIN_URL = '/login/' WAGTAIL_FRONTEND_LOGIN_URL = '/login/'
WAGTAIL_SITE_NAME = 'hypha' WAGTAIL_SITE_NAME = 'hypha'
WAGTAILIMAGES_IMAGE_MODEL = 'images.CustomImage' WAGTAILIMAGES_IMAGE_MODEL = 'images.CustomImage'
WAGTAILIMAGES_FEATURE_DETECTION_ENABLED = False WAGTAILIMAGES_FEATURE_DETECTION_ENABLED = False
...@@ -485,17 +439,11 @@ DEFAULT_PER_PAGE = 20 ...@@ -485,17 +439,11 @@ DEFAULT_PER_PAGE = 20
ESI_ENABLED = False ESI_ENABLED = False
# Custom settings
ENABLE_STYLEGUIDE = False ENABLE_STYLEGUIDE = False
DEBUGTOOLBAR = False DEBUGTOOLBAR = False
# Staff e-mail domain # Staff e-mail domain
STAFF_EMAIL_DOMAINS = env.list('STAFF_EMAIL_DOMAINS', [])
if 'STAFF_EMAIL_DOMAINS' in env:
STAFF_EMAIL_DOMAINS = env['STAFF_EMAIL_DOMAINS'].split(',')
else:
STAFF_EMAIL_DOMAINS = []
# Social Auth # Social Auth
SOCIAL_AUTH_URL_NAMESPACE = 'social' SOCIAL_AUTH_URL_NAMESPACE = 'social'
...@@ -503,13 +451,10 @@ SOCIAL_AUTH_URL_NAMESPACE = 'social' ...@@ -503,13 +451,10 @@ SOCIAL_AUTH_URL_NAMESPACE = 'social'
# Set the Google OAuth2 credentials in ENV variables or local.py # Set the Google OAuth2 credentials in ENV variables or local.py
# To create a new set of credentials, go to https://console.developers.google.com/apis/credentials # To create a new set of credentials, go to https://console.developers.google.com/apis/credentials
# Make sure the Google+ API is enabled for your API project # Make sure the Google+ API is enabled for your API project
if 'SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS' in env: SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = env.list('SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS', STAFF_EMAIL_DOMAINS)
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = env['SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS'].split(',')
else:
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = STAFF_EMAIL_DOMAINS
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = env.get('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY', '') SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = env.str('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY', '')
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = env.get('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET', '') SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = env.str('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET', '')
SOCIAL_AUTH_LOGIN_ERROR_URL = 'users_public:login' SOCIAL_AUTH_LOGIN_ERROR_URL = 'users_public:login'
SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = 'users:account' SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = 'users:account'
...@@ -531,13 +476,9 @@ SOCIAL_AUTH_PIPELINE = ( ...@@ -531,13 +476,9 @@ SOCIAL_AUTH_PIPELINE = (
# Bleach Settings # Bleach Settings
BLEACH_ALLOWED_TAGS = ['a', 'b', 'big', 'blockquote', 'br', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'li', 'ol', 'p', 'pre', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th', 'thead', 'tr', 'ul'] BLEACH_ALLOWED_TAGS = ['a', 'b', 'big', 'blockquote', 'br', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'li', 'ol', 'p', 'pre', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th', 'thead', 'tr', 'ul']
BLEACH_ALLOWED_ATTRIBUTES = ['class', 'colspan', 'href', 'rowspan', 'target', 'title', 'width'] BLEACH_ALLOWED_ATTRIBUTES = ['class', 'colspan', 'href', 'rowspan', 'target', 'title', 'width']
BLEACH_ALLOWED_STYLES = [] BLEACH_ALLOWED_STYLES = []
BLEACH_STRIP_TAGS = True BLEACH_STRIP_TAGS = True
BLEACH_STRIP_COMMENTS = True BLEACH_STRIP_COMMENTS = True
# File Field settings # File Field settings
...@@ -554,138 +495,85 @@ HIJACK_PERMISSION_CHECK = 'hijack.permissions.superusers_and_staff' ...@@ -554,138 +495,85 @@ HIJACK_PERMISSION_CHECK = 'hijack.permissions.superusers_and_staff'
# Messaging Settings # Messaging Settings
SEND_MESSAGES = env.get('SEND_MESSAGES', 'false').lower() == 'true' SEND_MESSAGES = env.bool('SEND_MESSAGES', False)
if not SEND_MESSAGES: if not SEND_MESSAGES:
from django.contrib.messages import constants as message_constants from django.contrib.messages import constants as message_constants
MESSAGE_LEVEL = message_constants.DEBUG MESSAGE_LEVEL = message_constants.DEBUG
SEND_READY_FOR_REVIEW = env.get('SEND_READY_FOR_REVIEW', 'true').lower() == 'true' SEND_READY_FOR_REVIEW = env.bool('SEND_READY_FOR_REVIEW', True)
SLACK_DESTINATION_URL = env.get('SLACK_DESTINATION_URL', None)
SLACK_DESTINATION_ROOM = env.get('SLACK_DESTINATION_ROOM', None)
SLACK_DESTINATION_ROOM_COMMENTS = env.get('SLACK_DESTINATION_ROOM_COMMENTS', None)
if 'SLACK_TYPE_COMMENTS' in env:
SLACK_TYPE_COMMENTS = env['SLACK_TYPE_COMMENTS'].split(',')
else:
SLACK_TYPE_COMMENTS = []
SLACK_DESTINATION_URL = env.url('SLACK_DESTINATION_URL', None)
SLACK_DESTINATION_ROOM = env.str('SLACK_DESTINATION_ROOM', None)
SLACK_DESTINATION_ROOM_COMMENTS = env.str('SLACK_DESTINATION_ROOM_COMMENTS', None)
SLACK_TYPE_COMMENTS = env.list('SLACK_TYPE_COMMENTS', [])
# Automatic transition settings # Automatic transition settings
TRANSITION_AFTER_REVIEWS = False TRANSITION_AFTER_REVIEWS = env.bool('TRANSITION_AFTER_REVIEWS', False)
if 'TRANSITION_AFTER_REVIEWS' in env: TRANSITION_AFTER_ASSIGNED = env.bool('TRANSITION_AFTER_ASSIGNED', False)
try:
TRANSITION_AFTER_REVIEWS = int(env['TRANSITION_AFTER_REVIEWS'])
except ValueError:
pass
TRANSITION_AFTER_ASSIGNED = False
if env.get('TRANSITION_AFTER_ASSIGNED', 'false').strip().lower() == 'true':
TRANSITION_AFTER_ASSIGNED = True
# Exclude Filters/columns from submission tables. # Exclude Filters/columns from submission tables.
# Possible values are: fund, round, status, lead, reviewers, screening_statuses, category_options, meta_terms # Possible values are: fund, round, status, lead, reviewers, screening_statuses, category_options, meta_terms
if 'SUBMISSIONS_TABLE_EXCLUDED_FIELDS' in env: SUBMISSIONS_TABLE_EXCLUDED_FIELDS = env.list('SUBMISSIONS_TABLE_EXCLUDED_FIELDS', [])
SUBMISSIONS_TABLE_EXCLUDED_FIELDS = env['SUBMISSIONS_TABLE_EXCLUDED_FIELDS'].split(',')
else:
SUBMISSIONS_TABLE_EXCLUDED_FIELDS = []
# Celery config # Celery config
if 'REDIS_URL' in env: if env.str('REDIS_URL', None):
CELERY_BROKER_URL = env.get('REDIS_URL') CELERY_BROKER_URL = env.str('REDIS_URL')
else: else:
CELERY_TASK_ALWAYS_EAGER = True CELERY_TASK_ALWAYS_EAGER = True
# S3 configuration # S3 configuration
if env.str('AWS_STORAGE_BUCKET_NAME', None):
if 'AWS_STORAGE_BUCKET_NAME' in env:
DEFAULT_FILE_STORAGE = 'hypha.storage_backends.PublicMediaStorage' DEFAULT_FILE_STORAGE = 'hypha.storage_backends.PublicMediaStorage'
PRIVATE_FILE_STORAGE = 'hypha.storage_backends.PrivateMediaStorage' PRIVATE_FILE_STORAGE = 'hypha.storage_backends.PrivateMediaStorage'
AWS_STORAGE_BUCKET_NAME = env.str('AWS_STORAGE_BUCKET_NAME')
AWS_STORAGE_BUCKET_NAME = env['AWS_STORAGE_BUCKET_NAME'] AWS_PUBLIC_BUCKET_NAME = env.str('AWS_PUBLIC_BUCKET_NAME', AWS_STORAGE_BUCKET_NAME)
AWS_PRIVATE_BUCKET_NAME = env.str('AWS_PRIVATE_BUCKET_NAME', AWS_STORAGE_BUCKET_NAME)
if 'AWS_PUBLIC_BUCKET_NAME' in env: AWS_S3_CUSTOM_DOMAIN = env.str('AWS_S3_CUSTOM_DOMAIN', None)
AWS_PUBLIC_BUCKET_NAME = env['AWS_PUBLIC_BUCKET_NAME'] AWS_PRIVATE_CUSTOM_DOMAIN = env.str('AWS_PRIVATE_CUSTOM_DOMAIN', None)
else: AWS_QUERYSTRING_EXPIRE = env.str('AWS_QUERYSTRING_EXPIRE', None)
AWS_PUBLIC_BUCKET_NAME = env['AWS_STORAGE_BUCKET_NAME'] AWS_PUBLIC_CUSTOM_DOMAIN = env.str('AWS_PUBLIC_CUSTOM_DOMAIN', None)
if 'AWS_PRIVATE_BUCKET_NAME' in env:
AWS_PRIVATE_BUCKET_NAME = env['AWS_PRIVATE_BUCKET_NAME']
else:
AWS_PRIVATE_BUCKET_NAME = env['AWS_STORAGE_BUCKET_NAME']
if 'AWS_S3_CUSTOM_DOMAIN' in env:
AWS_S3_CUSTOM_DOMAIN = env['AWS_S3_CUSTOM_DOMAIN']
if 'AWS_PRIVATE_CUSTOM_DOMAIN' in env:
AWS_PRIVATE_CUSTOM_DOMAIN = env['AWS_PRIVATE_CUSTOM_DOMAIN']
if 'AWS_QUERYSTRING_EXPIRE' in env:
AWS_QUERYSTRING_EXPIRE = env['AWS_QUERYSTRING_EXPIRE']
if 'AWS_PUBLIC_CUSTOM_DOMAIN' in env:
AWS_PUBLIC_CUSTOM_DOMAIN = env['AWS_PUBLIC_CUSTOM_DOMAIN']
INSTALLED_APPS += ( INSTALLED_APPS += (
'storages', 'storages',
) )
# Settings to connect to the Bucket from which we are migrating data # Settings to connect to the Bucket from which we are migrating data
AWS_MIGRATION_BUCKET_NAME = env.get('AWS_MIGRATION_BUCKET_NAME', '') AWS_MIGRATION_BUCKET_NAME = env.str('AWS_MIGRATION_BUCKET_NAME', '')
AWS_MIGRATION_ACCESS_KEY_ID = env.get('AWS_MIGRATION_ACCESS_KEY_ID', '') AWS_MIGRATION_ACCESS_KEY_ID = env.str('AWS_MIGRATION_ACCESS_KEY_ID', '')
AWS_MIGRATION_SECRET_ACCESS_KEY = env.get('AWS_MIGRATION_SECRET_ACCESS_KEY', '') AWS_MIGRATION_SECRET_ACCESS_KEY = env.str('AWS_MIGRATION_SECRET_ACCESS_KEY', '')
# Mailchimp settings.
MAILCHIMP_API_KEY = env.get('MAILCHIMP_API_KEY') MAILCHIMP_API_KEY = env.str('MAILCHIMP_API_KEY', None)
MAILCHIMP_LIST_ID = env.get('MAILCHIMP_LIST_ID') MAILCHIMP_LIST_ID = env.str('MAILCHIMP_LIST_ID', None)
# Basic auth settings # Basic auth settings
if env.get('BASIC_AUTH_ENABLED', 'false').lower().strip() == 'true': if env.bool('BASIC_AUTH_ENABLED', False):
MIDDLEWARE.insert(0, 'baipw.middleware.BasicAuthIPWhitelistMiddleware') MIDDLEWARE.insert(0, 'baipw.middleware.BasicAuthIPWhitelistMiddleware')
BASIC_AUTH_LOGIN = env['BASIC_AUTH_LOGIN'] BASIC_AUTH_LOGIN = env.str('BASIC_AUTH_LOGIN', None)
BASIC_AUTH_PASSWORD = env['BASIC_AUTH_PASSWORD'] BASIC_AUTH_PASSWORD = env.str('BASIC_AUTH_PASSWORD', None)
if 'BASIC_AUTH_WHITELISTED_HTTP_HOSTS' in env: BASIC_AUTH_WHITELISTED_HTTP_HOSTS = env.list('BASIC_AUTH_WHITELISTED_HTTP_HOSTS', [])
BASIC_AUTH_WHITELISTED_HTTP_HOSTS = ( BASIC_AUTH_WHITELISTED_IP_NETWORKS = env.list('BASIC_AUTH_WHITELISTED_IP_NETWORKS', [])
env['BASIC_AUTH_WHITELISTED_HTTP_HOSTS'].split(',')
)
if 'BASIC_AUTH_WHITELISTED_IP_NETWORKS' in env: if env.str('PRIMARY_HOST', None):
BASIC_AUTH_WHITELISTED_IP_NETWORKS = (
env['BASIC_AUTH_WHITELISTED_IP_NETWORKS'].split(',')
)
if 'PRIMARY_HOST' in env:
# This is used by Wagtail's email notifications for constructing absolute # This is used by Wagtail's email notifications for constructing absolute
# URLs. # URLs.
BASE_URL = 'https://{}'.format(env['PRIMARY_HOST']) BASE_URL = 'https://{}'.format(env.str('PRIMARY_HOST'))
# Security configuration # Security configuration
# https://docs.djangoproject.com/en/stable/ref/middleware/#module-django.middleware.security # https://docs.djangoproject.com/en/stable/ref/middleware/#module-django.middleware.security
SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', True)
if env.get('SECURE_SSL_REDIRECT', 'true').strip().lower() == 'true':
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_HSTS_SECONDS = env.int('SECURE_HSTS_SECONDS', None)
SECURE_BROWSER_XSS_FILTER = env.bool('SECURE_BROWSER_XSS_FILTER', True)
SECURE_CONTENT_TYPE_NOSNIFF = env.bool('SECURE_CONTENT_TYPE_NOSNIFF', True)
if 'SECURE_HSTS_SECONDS' in env: if env.bool('COOKIE_SECURE', False):
try:
SECURE_HSTS_SECONDS = int(env['SECURE_HSTS_SECONDS'])
except ValueError:
pass
if env.get('SECURE_BROWSER_XSS_FILTER', 'true').lower().strip() == 'true':
SECURE_BROWSER_XSS_FILTER = True
if env.get('SECURE_CONTENT_TYPE_NOSNIFF', 'true').lower().strip() == 'true':
SECURE_CONTENT_TYPE_NOSNIFF = True
if env.get('COOKIE_SECURE', 'false').lower().strip() == 'true':
SESSION_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True
...@@ -693,13 +581,12 @@ if env.get('COOKIE_SECURE', 'false').lower().strip() == 'true': ...@@ -693,13 +581,12 @@ if env.get('COOKIE_SECURE', 'false').lower().strip() == 'true':
# Referrer-policy header settings # Referrer-policy header settings
# https://django-referrer-policy.readthedocs.io/en/1.0/ # https://django-referrer-policy.readthedocs.io/en/1.0/
REFERRER_POLICY = env.get('SECURE_REFERRER_POLICY', REFERRER_POLICY = env.str('SECURE_REFERRER_POLICY',
'no-referrer-when-downgrade').strip() 'no-referrer-when-downgrade').strip()
# Webpack bundle loader # Webpack bundle loader
# When disabled, all included bundles are silently ignored. # When disabled, all included bundles are silently ignored.
if env.get('ENABLE_WEBPACK_BUNDLES', 'true').lower().strip() == 'true': ENABLE_WEBPACK_BUNDLES = env.bool('ENABLE_WEBPACK_BUNDLES', True)
ENABLE_WEBPACK_BUNDLES = True
WEBPACK_LOADER = { WEBPACK_LOADER = {
'DEFAULT': { 'DEFAULT': {
...@@ -727,27 +614,21 @@ REST_FRAMEWORK = { ...@@ -727,27 +614,21 @@ REST_FRAMEWORK = {
# Projects Feature Flag # Projects Feature Flag
PROJECTS_ENABLED = False PROJECTS_ENABLED = env.bool('PROJECTS_ENABLED', False)
if env.get('PROJECTS_ENABLED', 'false').lower().strip() == 'true':
PROJECTS_ENABLED = True
PROJECTS_AUTO_CREATE = False
if env.get('PROJECTS_AUTO_CREATE', 'false').lower().strip() == 'true':
PROJECTS_AUTO_CREATE = True
PROJECTS_AUTO_CREATE = env.bool('PROJECTS_AUTO_CREATE', False)
# Salesforce integration # Salesforce integration
if env.bool('SALESFORCE_INTEGRATION', False):
if env.get('SALESFORCE_INTEGRATION', 'false').lower().strip() == 'true':
DATABASES = { DATABASES = {
**DATABASES, **DATABASES,
'salesforce': { 'salesforce': {
'ENGINE': 'salesforce.backend', 'ENGINE': 'salesforce.backend',
'CONSUMER_KEY': env.get('SALESFORCE_CONSUMER_KEY', ''), 'CONSUMER_KEY': env.str('SALESFORCE_CONSUMER_KEY', ''),
'CONSUMER_SECRET': env.get('SALESFORCE_CONSUMER_SECRET', ''), 'CONSUMER_SECRET': env.str('SALESFORCE_CONSUMER_SECRET', ''),
'USER': env.get('SALESFORCE_USER', ''), 'USER': env.str('SALESFORCE_USER', ''),
'PASSWORD': env.get('SALESFORCE_PASSWORD', ''), 'PASSWORD': env.str('SALESFORCE_PASSWORD', ''),
'HOST': env.get('SALESFORCE_LOGIN_URL', '') 'HOST': env.str('SALESFORCE_LOGIN_URL', '')
} }
} }
...@@ -759,17 +640,14 @@ if env.get('SALESFORCE_INTEGRATION', 'false').lower().strip() == 'true': ...@@ -759,17 +640,14 @@ if env.get('SALESFORCE_INTEGRATION', 'false').lower().strip() == 'true':
# django-file-form settings # django-file-form settings
FILE_FORM_CACHE = 'django_file_form' FILE_FORM_CACHE = 'django_file_form'
FILE_FORM_UPLOAD_DIR = 'temp_uploads' FILE_FORM_UPLOAD_DIR = 'temp_uploads'
# Ensure FILE_FORM_UPLOAD_DIR exists: # Ensure FILE_FORM_UPLOAD_DIR exists:
os.makedirs(os.path.join(MEDIA_ROOT, FILE_FORM_UPLOAD_DIR), exist_ok=True) os.makedirs(os.path.join(MEDIA_ROOT, FILE_FORM_UPLOAD_DIR), exist_ok=True)
# Store temporary files on S3 too (files are still uploaded to local filesystem first) # Store temporary files on S3 too (files are still uploaded to local filesystem first)
if 'AWS_STORAGE_BUCKET_NAME' in env: if env.str('AWS_STORAGE_BUCKET_NAME', None):
FILE_FORM_TEMP_STORAGE = PRIVATE_FILE_STORAGE FILE_FORM_TEMP_STORAGE = PRIVATE_FILE_STORAGE
# Matomo tracking # Matomo tracking
MATOMO_URL = env.str('MATOMO_URL', None)
MATOMO_URL = env.get('MATOMO_URL', False) MATOMO_SITEID = env.str('MATOMO_SITEID', None)
MATOMO_SITEID = env.get('MATOMO_SITEID', False)
import os
from .base import * # noqa from .base import * # noqa
# Disable debug mode # Disable debug mode
DEBUG = False DEBUG = False
# Configuration from environment variables
env = os.environ.copy()
# Alternatively, you can set these in a local.py file on the server # Alternatively, you can set these in a local.py file on the server
try: try:
from .local import * # noqa from .local import * # noqa
...@@ -15,28 +10,28 @@ except ImportError: ...@@ -15,28 +10,28 @@ except ImportError:
pass pass
# Mailgun configuration. # Mailgun configuration.
if 'MAILGUN_API_KEY' in env: if env.str('MAILGUN_API_KEY', None):
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend' EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend'
ANYMAIL = { ANYMAIL = {
'MAILGUN_API_KEY': env['MAILGUN_API_KEY'], 'MAILGUN_API_KEY': env.str('MAILGUN_API_KEY'),
'MAILGUN_SENDER_DOMAIN': env.get('EMAIL_HOST', None), 'MAILGUN_SENDER_DOMAIN': env.str('EMAIL_HOST', None),
'MAILGUN_API_URL': env.get('MAILGUN_API_URL', 'https://api.mailgun.net/v3'), 'MAILGUN_API_URL': env.url('MAILGUN_API_URL', 'https://api.mailgun.net/v3'),
'WEBHOOK_SECRET': env.get('ANYMAIL_WEBHOOK_SECRET', None) 'WEBHOOK_SECRET': env.str('ANYMAIL_WEBHOOK_SECRET', None)
} }
# Sentry configuration. # Sentry configuration.
if 'SENTRY_DSN' in env: if env.str('SENTRY_DSN', None):
import sentry_sdk import sentry_sdk
from sentry_sdk.integrations.celery import CeleryIntegration from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init( sentry_sdk.init(
dsn=env['SENTRY_DSN'], dsn=env.str('SENTRY_DSN'),
environment=env.get('SENTRY_ENVIRONMENT', None), environment=env.str('SENTRY_ENVIRONMENT', None),
integrations=[DjangoIntegration(), CeleryIntegration()] integrations=[DjangoIntegration(), CeleryIntegration()]
) )
# Heroku configuration. # Heroku configuration.
# Set ON_HEROKU to true in Config Vars or via cli 'heroku config:set ON_HEROKU=true'. # Set ON_HEROKU to true in Config Vars or via cli 'heroku config:set ON_HEROKU=true'.
if 'ON_HEROKU' in env: if env.bool('ON_HEROKU', False):
import django_heroku import django_heroku
django_heroku.settings(locals()) django_heroku.settings(locals())
...@@ -33,6 +33,7 @@ djangorestframework-api-key==2.1.0 ...@@ -33,6 +33,7 @@ djangorestframework-api-key==2.1.0
djangorestframework==3.12.4 djangorestframework==3.12.4
drf-nested-routers==0.93.4 drf-nested-routers==0.93.4
drf-yasg==1.20.0 drf-yasg==1.20.0
environs==9.5.0
gunicorn==20.1.0 gunicorn==20.1.0
mailchimp3==3.0.16 mailchimp3==3.0.16
mistune==0.8.4 mistune==0.8.4
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment