settings.py
1 import os 2 import dj_database_url 3 import re 4 from django.conf import settings 5 from django.core.urlresolvers import reverse_lazy 6 from cabot.settings_utils import environ_get_list, force_bool 7 from cabot.cabot_config import * 8 9 settings_dir = os.path.dirname(__file__) 10 PROJECT_ROOT = os.path.abspath(settings_dir) 11 12 DEBUG = force_bool(os.environ.get('DEBUG', False)) 13 14 ADMINS = ( 15 ('Admin', os.environ.get('ADMIN_EMAIL', 'name@example.com')), 16 ) 17 18 MANAGERS = ADMINS 19 20 if os.environ.get('CABOT_FROM_EMAIL'): 21 DEFAULT_FROM_EMAIL = os.environ['CABOT_FROM_EMAIL'] 22 23 DATABASES = {'default': dj_database_url.config()} 24 25 TEST_RUNNER = 'django.test.runner.DiscoverRunner' 26 27 URL_PREFIX = os.environ.get('URL_PREFIX', '/').rstrip('/') 28 29 LOGIN_URL = os.environ.get('LOGIN_URL', reverse_lazy('login')) 30 LOGIN_REDIRECT_URL = reverse_lazy('services') 31 32 USE_TZ = True 33 34 ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(',') 35 36 # Local time zone for this installation. Choices can be found here: 37 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 38 # although not all choices may be available on all operating systems. 39 # On Unix systems, a value of None will cause Django to use the same 40 # timezone as the operating system. 41 # If running in a Windows environment this must be set to the same as your 42 # system time zone. 43 TIME_ZONE = os.environ.get('TIME_ZONE', 'Etc/UTC') 44 45 # Language code for this installation. All choices can be found here: 46 # http://www.i18nguy.com/unicode/language-identifiers.html 47 LANGUAGE_CODE = 'en-us' 48 49 SITE_ID = 1 50 51 # If you set this to False, Django will make some optimizations so as not 52 # to load the internationalization machinery. 53 USE_I18N = True 54 55 # If you set this to False, Django will not format dates, numbers and 56 # calendars according to the current locale 57 USE_L10N = True 58 59 # Absolute filesystem path to the directory that will hold user-uploaded files. 60 # Example: "/home/media/media.lawrence.com/media/" 61 MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media/') 62 63 # URL that handles the media served from MEDIA_ROOT. Make sure to use a 64 # trailing slash. 65 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 66 MEDIA_URL = '%s/media/' % URL_PREFIX 67 68 # Absolute path to the directory static files should be collected to. 69 # Don't put anything in this directory yourself; store your static files 70 # in apps' "static/" subdirectories and in STATICFILES_DIRS. 71 # Example: "/home/media/media.lawrence.com/static/" 72 STATIC_ROOT = os.path.join(PROJECT_ROOT, '.collectstatic/') 73 74 COMPRESS_ROOT = STATIC_ROOT 75 76 # URL prefix for static files. 77 # Example: "http://media.lawrence.com/static/" 78 STATIC_URL = '%s/static/' % URL_PREFIX 79 COMPRESS_URL = STATIC_URL 80 81 # Additional locations of static files 82 STATICFILES_DIRS = [os.path.join(PROJECT_ROOT, 'static')] 83 84 if not DEBUG: 85 STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' 86 87 # List of finder classes that know how to find static files in 88 # various locations. 89 STATICFILES_FINDERS = ( 90 'django.contrib.staticfiles.finders.FileSystemFinder', 91 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 92 'compressor.finders.CompressorFinder', 93 ) 94 95 if os.environ.get('WWW_SCHEME') == 'https': 96 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') 97 98 # Make this unique, and don't share it with anybody. 99 SECRET_KEY = os.environ.get( 100 'DJANGO_SECRET_KEY', '2FL6ORhHwr5eX34pP9mMugnIOd3jzVuT45f7w430Mt5PnEwbcJgma0q8zUXNZ68A') 101 102 # List of callables that know how to import templates from various sources. 103 TEMPLATES = [{ 104 'BACKEND': 'django.template.backends.django.DjangoTemplates', 105 'DIRS': ( 106 os.path.join(PROJECT_ROOT, 'templates'), 107 ), 108 'APP_DIRS': True, 109 'OPTIONS': { 110 'context_processors': [ 111 'django.template.context_processors.debug', 112 'django.template.context_processors.request', 113 'django.contrib.auth.context_processors.auth', 114 'django.contrib.messages.context_processors.messages', 115 'cabot.context_processors.global_settings', 116 ], 117 'debug': force_bool(os.environ.get('TEMPLATE_DEBUG', False)) 118 }, 119 }] 120 121 MIDDLEWARE_CLASSES = ( 122 'whitenoise.middleware.WhiteNoiseMiddleware', 123 'django.middleware.common.CommonMiddleware', 124 'django.contrib.sessions.middleware.SessionMiddleware', 125 'django.middleware.csrf.CsrfViewMiddleware', 126 'django.contrib.auth.middleware.AuthenticationMiddleware', 127 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 128 'django.contrib.messages.middleware.MessageMiddleware', 129 ) 130 131 ROOT_URLCONF = 'cabot.urls' 132 INSTALLED_APPS = ( 133 'django.contrib.auth', 134 'django.contrib.contenttypes', 135 'django.contrib.sessions', 136 'django.contrib.sites', 137 'django.contrib.messages', 138 'django.contrib.staticfiles', 139 # Uncomment the next line to enable admin documentation: 140 # 'django.contrib.admindocs', 141 'django_filters', 142 'compressor', 143 'polymorphic', 144 'jsonify', 145 'cabot.cabotapp', 146 'rest_framework', 147 'dal', 148 'dal_select2', 149 'django.contrib.admin', 150 'bootstrapform', 151 ) 152 153 AUTH_USER_MODEL = 'auth.User' 154 155 # Load additional apps from configuration file 156 CABOT_PLUGINS_ENABLED_PARSED = [] 157 for plugin in CABOT_PLUGINS_ENABLED.split(","): 158 # Hack to clean up if versions of plugins specified 159 exploded = re.split(r'[<>=]+', plugin) 160 CABOT_PLUGINS_ENABLED_PARSED.append(exploded[0]) 161 162 INSTALLED_APPS += tuple(CABOT_PLUGINS_ENABLED_PARSED) 163 164 COMPRESS_PRECOMPILERS = ( 165 ('text/coffeescript', 'coffee --compile --stdio'), 166 ('text/eco', 167 'eco -i TEMPLATES {infile} && cat "$(echo "{infile}" | sed -e "s/\.eco$/.js/g")"'), 168 ('text/less', 'lessc {infile} > {outfile}'), 169 ) 170 171 # For the email settings we both accept old and new names 172 EMAIL_HOST = environ_get_list(['EMAIL_HOST', 'SES_HOST'], 'localhost') 173 EMAIL_PORT = int(environ_get_list(['EMAIL_PORT', 'SES_PORT'], 25)) 174 EMAIL_HOST_USER = environ_get_list(['EMAIL_USER', 'SES_USER'], '') 175 EMAIL_HOST_PASSWORD = environ_get_list(['EMAIL_PASSWORD', 'SES_PASS'], '') 176 EMAIL_BACKEND = environ_get_list( 177 ['EMAIL_BACKEND', 'SES_BACKEND'], 178 'django.core.mail.backends.smtp.EmailBackend' 179 ) 180 EMAIL_USE_TLS = force_bool(environ_get_list(['EMAIL_USE_TLS', 'SES_USE_TLS'], False)) 181 EMAIL_USE_SSL = force_bool(environ_get_list(['EMAIL_USE_SSL', 'SES_USE_SSL'], not EMAIL_USE_TLS)) 182 183 COMPRESS_OFFLINE = not DEBUG 184 185 RECOVERY_SNIPPETS_WHITELIST = ( 186 r'https?://[^.]+\.hackpad\.com/[^./]+\.js', 187 r'https?://gist\.github\.com/[^.]+\.js', 188 r'https?://www\.refheap\.com/[^.]+\.js', 189 ) 190 191 # A sample logging configuration. The only tangible logging 192 # performed by this configuration is to send an email to 193 # the site admins on every HTTP 500 error. 194 # See http://docs.djangoproject.com/en/dev/topics/logging for 195 # more details on how to customize your logging configuration. 196 LOGGING = { 197 'version': 1, 198 'disable_existing_loggers': True, 199 'formatters': { 200 'verbose': { 201 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' 202 }, 203 'simple': { 204 'format': '%(levelname)s %(message)s' 205 }, 206 }, 207 'handlers': { 208 'null': { 209 'level': 'DEBUG', 210 'class': 'logging.NullHandler', 211 }, 212 'console': { 213 'level': 'DEBUG', 214 'class': 'logging.StreamHandler', 215 'formatter': 'verbose' 216 }, 217 'log_file': { 218 'level': 'DEBUG', 219 'class': 'logging.handlers.RotatingFileHandler', 220 'formatter': 'verbose', 221 'filename': os.environ.get('LOG_FILE', '/dev/null'), 222 'maxBytes': 1024 * 1024 * 25, # 25 MB 223 'backupCount': 5, 224 }, 225 'mail_admins': { 226 'level': 'ERROR', 227 'class': 'django.utils.log.AdminEmailHandler' 228 } 229 }, 230 'loggers': { 231 'django': { 232 'handlers': ['console', 'log_file', 'mail_admins'], 233 'level': 'INFO', 234 'propagate': True, 235 }, 236 'django.request': { 237 'handlers': ['console', 'log_file', 'mail_admins'], 238 'level': 'ERROR', 239 'propagate': False, 240 }, 241 'django.db.backends': { 242 'handlers': ['console', 'log_file', 'mail_admins'], 243 'level': 'INFO', 244 'propagate': False, 245 }, 246 # Catch All Logger -- Captures any other logging 247 '': { 248 'handlers': ['console', 'log_file', 'mail_admins'], 249 'level': 'INFO', 250 'propagate': True, 251 } 252 } 253 } 254 255 REST_FRAMEWORK = { 256 'DEFAULT_AUTHENTICATION_CLASSES': ( 257 'rest_framework.authentication.BasicAuthentication', 258 'rest_framework.authentication.SessionAuthentication', 259 ), 260 'DEFAULT_PERMISSION_CLASSES': [ 261 'rest_framework.permissions.DjangoModelPermissions', 262 ], 263 'DEFAULT_FILTER_BACKENDS': [ 264 'django_filters.rest_framework.DjangoFilterBackend', 265 'rest_framework.filters.OrderingFilter', 266 ] 267 } 268 269 AUTHENTICATION_BACKENDS = ( 270 'django.contrib.auth.backends.ModelBackend', 271 ) 272 273 AUTH_LDAP = force_bool(os.environ.get('AUTH_LDAP', False)) 274 275 if AUTH_LDAP: 276 from settings_ldap import * 277 AUTHENTICATION_BACKENDS += tuple(['django_auth_ldap.backend.LDAPBackend']) 278 279 # Github SSO 280 AUTH_GITHUB_ENTERPRISE_ORG = force_bool(os.environ.get('AUTH_GITHUB_ENTERPRISE_ORG', False)) 281 AUTH_GITHUB_ORG = force_bool(os.environ.get('AUTH_GITHUB_ORG', False)) 282 AUTH_GOOGLE_OAUTH2 = force_bool(os.environ.get('AUTH_GOOGLE_OAUTH2', False)) 283 284 AUTH_SOCIAL = AUTH_GITHUB_ORG or AUTH_GITHUB_ENTERPRISE_ORG or AUTH_GOOGLE_OAUTH2 285 SOCIAL_AUTH_REDIRECT_IS_HTTPS = force_bool(os.environ.get('SOCIAL_AUTH_REDIRECT_IS_HTTPS', False)) 286 287 if AUTH_SOCIAL: 288 SOCIAL_AUTH_URL_NAMESPACE = 'social' 289 INSTALLED_APPS += tuple(['social_django']) 290 291 if AUTH_GITHUB_ORG: 292 AUTHENTICATION_BACKENDS += tuple(['social_core.backends.github.GithubOrganizationOAuth2']) 293 SOCIAL_AUTH_GITHUB_ORG_KEY = os.environ.get('AUTH_GITHUB_ORG_CLIENT_ID') 294 SOCIAL_AUTH_GITHUB_ORG_SECRET = os.environ.get('AUTH_GITHUB_ORG_CLIENT_SECRET') 295 SOCIAL_AUTH_GITHUB_ORG_NAME = os.environ.get('AUTH_GITHUB_ORG_NAME') 296 SOCIAL_AUTH_GITHUB_ORG_SCOPE = ['read:org'] 297 298 if AUTH_GITHUB_ENTERPRISE_ORG: 299 AUTHENTICATION_BACKENDS += tuple(['social_core.backends.github_enterprise.GithubEnterpriseOrganizationOAuth2']) 300 SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_URL = os.environ.get('AUTH_GITHUB_ENTERPRISE_ORG_URL') 301 SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_API_URL = os.environ.get('AUTH_GITHUB_ENTERPRISE_ORG_API_URL') 302 SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_KEY = os.environ.get('AUTH_GITHUB_ENTERPRISE_ORG_CLIENT_ID') 303 SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_SECRET = os.environ.get('AUTH_GITHUB_ENTERPRISE_ORG_CLIENT_SECRET') 304 SOCIAL_AUTH_GITHUB_ENTERPRISE_ORG_NAME = os.environ.get('AUTH_GITHUB_ENTERPRISE_ORG_NAME') 305 306 if AUTH_GOOGLE_OAUTH2: 307 AUTHENTICATION_BACKENDS += tuple(['social_core.backends.google.GoogleOAuth2']) 308 SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.environ.get('AUTH_GOOGLE_OAUTH2_KEY') 309 SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ.get('AUTH_GOOGLE_OAUTH2_SECRET') 310 SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = os.environ.get('AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS', '').split(',') 311 312 EXPOSE_USER_API = force_bool(os.environ.get('EXPOSE_USER_API', False)) 313 ENABLE_SUBSCRIPTION = force_bool(os.environ.get('ENABLE_SUBSCRIPTION', True)) 314 ENABLE_DUTY_ROTA = force_bool(os.environ.get('ENABLE_DUTY_ROTA', True))