settings.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #!/usr/bin/env python
  2. # Licensed to Cloudera, Inc. under one
  3. # or more contributor license agreements. See the NOTICE file
  4. # distributed with this work for additional information
  5. # regarding copyright ownership. Cloudera, Inc. licenses this file
  6. # to you under the Apache License, Version 2.0 (the
  7. # "License"); you may not use this file except in compliance
  8. # with the License. You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. # Django settings for Hue.
  18. #
  19. # Local customizations are done by symlinking a file
  20. # as local_settings.py.
  21. import logging
  22. import os
  23. import pkg_resources
  24. import sys
  25. from guppy import hpy
  26. import desktop.conf
  27. import desktop.log
  28. import desktop.redaction
  29. from desktop.lib.paths import get_desktop_root
  30. from desktop.lib.python_util import force_dict_to_strings
  31. # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
  32. BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), '..', '..', '..'))
  33. HUE_DESKTOP_VERSION = pkg_resources.get_distribution("desktop").version or "Unknown"
  34. NICE_NAME = "Hue"
  35. ENV_HUE_PROCESS_NAME = "HUE_PROCESS_NAME"
  36. ENV_DESKTOP_DEBUG = "DESKTOP_DEBUG"
  37. ############################################################
  38. # Part 1: Logging and imports.
  39. ############################################################
  40. # Configure debug mode
  41. DEBUG = True
  42. TEMPLATE_DEBUG = DEBUG
  43. # Start basic logging as soon as possible.
  44. if ENV_HUE_PROCESS_NAME not in os.environ:
  45. _proc = os.path.basename(len(sys.argv) > 1 and sys.argv[1] or sys.argv[0])
  46. os.environ[ENV_HUE_PROCESS_NAME] = _proc
  47. desktop.log.basic_logging(os.environ[ENV_HUE_PROCESS_NAME])
  48. logging.info("Welcome to Hue " + HUE_DESKTOP_VERSION)
  49. # Then we can safely import some more stuff
  50. from desktop import appmanager
  51. from desktop.lib import conf
  52. # Add fancy logging
  53. desktop.log.fancy_logging()
  54. ############################################################
  55. # Part 2: Generic Configuration
  56. ############################################################
  57. # Language code for this installation. All choices can be found here:
  58. # http://www.i18nguy.com/unicode/language-identifiers.html
  59. LANGUAGE_CODE = 'en-us'
  60. SITE_ID = 1
  61. # If you set this to False, Django will make some optimizations so as not
  62. # to load the internationalization machinery.
  63. USE_I18N = True
  64. # If you set this to False, Django will not format dates, numbers and
  65. # calendars according to the current locale.
  66. USE_L10N = True
  67. # If you set this to False, Django will not use timezone-aware datetimes.
  68. USE_TZ = False
  69. # URL that handles the media served from MEDIA_ROOT. Make sure to use a
  70. # trailing slash.
  71. # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
  72. MEDIA_URL = ''
  73. ############################################################
  74. # Part 3: Django configuration
  75. ############################################################
  76. # Additional locations of static files
  77. STATICFILES_DIRS = (
  78. os.path.join(BASE_DIR, 'desktop', 'libs', 'indexer', 'src', 'indexer', 'static'),
  79. os.path.join(BASE_DIR, 'desktop', 'libs', 'liboauth', 'src', 'liboauth', 'static'),
  80. )
  81. STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'
  82. # For Django admin interface
  83. STATIC_URL = '/static/'
  84. STATIC_ROOT = os.path.join(BASE_DIR, 'build', 'static')
  85. # List of callables that know how to import templates from various sources.
  86. TEMPLATE_LOADERS = (
  87. 'django.template.loaders.filesystem.Loader',
  88. 'django.template.loaders.app_directories.Loader'
  89. )
  90. MIDDLEWARE_CLASSES = [
  91. # The order matters
  92. 'desktop.middleware.MetricsMiddleware',
  93. 'desktop.middleware.EnsureSafeMethodMiddleware',
  94. 'desktop.middleware.AuditLoggingMiddleware',
  95. 'django.middleware.common.CommonMiddleware',
  96. 'django.contrib.sessions.middleware.SessionMiddleware',
  97. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  98. 'desktop.middleware.SpnegoMiddleware',
  99. 'desktop.middleware.HueRemoteUserMiddleware',
  100. 'django.middleware.locale.LocaleMiddleware',
  101. 'babeldjango.middleware.LocaleMiddleware',
  102. 'desktop.middleware.AjaxMiddleware',
  103. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  104. # Must be after Session, Auth, and Ajax. Before everything else.
  105. 'desktop.middleware.LoginAndPermissionMiddleware',
  106. 'django.contrib.messages.middleware.MessageMiddleware',
  107. 'desktop.middleware.NotificationMiddleware',
  108. 'desktop.middleware.ExceptionMiddleware',
  109. 'desktop.middleware.ClusterMiddleware',
  110. # 'debug_toolbar.middleware.DebugToolbarMiddleware'
  111. 'django.middleware.csrf.CsrfViewMiddleware',
  112. 'django.middleware.http.ConditionalGetMiddleware',
  113. ]
  114. if os.environ.get(ENV_DESKTOP_DEBUG):
  115. MIDDLEWARE_CLASSES.append('desktop.middleware.HtmlValidationMiddleware')
  116. logging.debug("Will try to validate generated HTML.")
  117. ROOT_URLCONF = 'desktop.urls'
  118. # Hue runs its own wsgi applications
  119. WSGI_APPLICATION = None
  120. TEMPLATE_DIRS = (
  121. get_desktop_root("core/templates"),
  122. )
  123. INSTALLED_APPS = [
  124. 'django.contrib.auth',
  125. 'django_openid_auth',
  126. 'django.contrib.contenttypes',
  127. 'django.contrib.sessions',
  128. 'django.contrib.sites',
  129. 'django.contrib.staticfiles',
  130. 'django.contrib.admin',
  131. 'django_extensions',
  132. # 'debug_toolbar',
  133. 'south', # database migration tool
  134. # i18n support
  135. 'babeldjango',
  136. # Desktop injects all the other installed apps into here magically.
  137. 'desktop'
  138. ]
  139. LOCALE_PATHS = [
  140. get_desktop_root('core/src/desktop/locale')
  141. ]
  142. # Keep default values up to date
  143. TEMPLATE_CONTEXT_PROCESSORS = (
  144. 'django.contrib.auth.context_processors.auth',
  145. 'django.core.context_processors.debug',
  146. 'django.core.context_processors.i18n',
  147. 'django.core.context_processors.media',
  148. 'django.core.context_processors.request',
  149. 'django.contrib.messages.context_processors.messages',
  150. # Not default
  151. 'desktop.context_processors.app_name',
  152. )
  153. # Desktop doesn't use an auth profile module, because
  154. # because it doesn't mesh very well with the notion
  155. # of having multiple apps. If your app needs
  156. # to store data related to users, it should
  157. # manage its own table with an appropriate foreign key.
  158. AUTH_PROFILE_MODULE=None
  159. LOGIN_REDIRECT_URL = "/"
  160. LOGOUT_REDIRECT_URL = "/" # For djangosaml2 bug.
  161. PYLINTRC = get_desktop_root('.pylintrc')
  162. # Insert our HDFS upload handler
  163. FILE_UPLOAD_HANDLERS = (
  164. 'hadoop.fs.upload.HDFSfileUploadHandler',
  165. 'django.core.files.uploadhandler.MemoryFileUploadHandler',
  166. 'django.core.files.uploadhandler.TemporaryFileUploadHandler',
  167. )
  168. # Custom CSRF Failure View
  169. CSRF_FAILURE_VIEW = 'desktop.views.csrf_failure'
  170. ############################################################
  171. # Part 4: Installation of apps
  172. ############################################################
  173. _config_dir = os.getenv("HUE_CONF_DIR", get_desktop_root("conf"))
  174. # Libraries are loaded and configured before the apps
  175. appmanager.load_libs()
  176. _lib_conf_modules = [dict(module=app.conf, config_key=None) for app in appmanager.DESKTOP_LIBS if app.conf is not None]
  177. LOCALE_PATHS.extend([app.locale_path for app in appmanager.DESKTOP_LIBS])
  178. # Load desktop config
  179. _desktop_conf_modules = [dict(module=desktop.conf, config_key=None)]
  180. conf.initialize(_desktop_conf_modules, _config_dir)
  181. # Register the redaction filters into the root logger as soon as possible.
  182. desktop.redaction.register_log_filtering(desktop.conf.get_redaction_policy())
  183. # Activate l10n
  184. # Install apps
  185. appmanager.load_apps(desktop.conf.APP_BLACKLIST.get())
  186. for app in appmanager.DESKTOP_APPS:
  187. INSTALLED_APPS.extend(app.django_apps)
  188. LOCALE_PATHS.append(app.locale_path)
  189. logging.debug("Installed Django modules: %s" % ",".join(map(str, appmanager.DESKTOP_MODULES)))
  190. # Load app configuration
  191. _app_conf_modules = [dict(module=app.conf, config_key=app.config_key) for app in appmanager.DESKTOP_APPS if app.conf is not None]
  192. conf.initialize(_lib_conf_modules, _config_dir)
  193. conf.initialize(_app_conf_modules, _config_dir)
  194. # Now that we've loaded the desktop conf, set the django DEBUG mode based on the conf.
  195. DEBUG = desktop.conf.DJANGO_DEBUG_MODE.get()
  196. TEMPLATE_DEBUG = DEBUG
  197. ############################################################
  198. # Part 4a: Django configuration that requires bound Desktop
  199. # configs.
  200. ############################################################
  201. # Configure allowed hosts
  202. ALLOWED_HOSTS = desktop.conf.ALLOWED_HOSTS.get()
  203. # Configure hue admins
  204. ADMINS = []
  205. for admin in desktop.conf.DJANGO_ADMINS.get():
  206. admin_conf = desktop.conf.DJANGO_ADMINS[admin]
  207. if 'name' in admin_conf.bind_to and 'email' in admin_conf.bind_to:
  208. ADMINS.append(((admin_conf.NAME.get(), admin_conf.EMAIL.get())))
  209. ADMINS = tuple(ADMINS)
  210. MANAGERS = ADMINS
  211. # Server Email Address
  212. SERVER_EMAIL = desktop.conf.DJANGO_SERVER_EMAIL.get()
  213. # Email backend
  214. EMAIL_BACKEND = desktop.conf.DJANGO_EMAIL_BACKEND.get()
  215. # Configure database
  216. if os.getenv('DESKTOP_DB_CONFIG'):
  217. conn_string = os.getenv('DESKTOP_DB_CONFIG')
  218. logging.debug("DESKTOP_DB_CONFIG SET: %s" % (conn_string))
  219. default_db = dict(zip(
  220. ["ENGINE", "NAME", "TEST_NAME", "USER", "PASSWORD", "HOST", "PORT"],
  221. conn_string.split(':')))
  222. else:
  223. test_name = os.environ.get('DESKTOP_DB_TEST_NAME', get_desktop_root('desktop-test.db'))
  224. logging.debug("DESKTOP_DB_TEST_NAME SET: %s" % test_name)
  225. default_db = {
  226. "ENGINE" : desktop.conf.DATABASE.ENGINE.get(),
  227. "NAME" : desktop.conf.DATABASE.NAME.get(),
  228. "USER" : desktop.conf.DATABASE.USER.get(),
  229. "PASSWORD" : desktop.conf.get_database_password(),
  230. "HOST" : desktop.conf.DATABASE.HOST.get(),
  231. "PORT" : str(desktop.conf.DATABASE.PORT.get()),
  232. "OPTIONS": force_dict_to_strings(desktop.conf.DATABASE.OPTIONS.get()),
  233. # DB used for tests
  234. "TEST_NAME" : test_name,
  235. # Wrap each request in a transaction.
  236. "ATOMIC_REQUESTS" : True,
  237. }
  238. DATABASES = {
  239. 'default': default_db
  240. }
  241. CACHES = {
  242. 'default': {
  243. 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
  244. 'LOCATION': 'unique-hue'
  245. }
  246. }
  247. # Configure sessions
  248. SESSION_COOKIE_AGE = desktop.conf.SESSION.TTL.get()
  249. SESSION_COOKIE_SECURE = desktop.conf.SESSION.SECURE.get()
  250. SESSION_EXPIRE_AT_BROWSER_CLOSE = desktop.conf.SESSION.EXPIRE_AT_BROWSER_CLOSE.get()
  251. # HTTP only
  252. SESSION_COOKIE_HTTPONLY = desktop.conf.SESSION.HTTP_ONLY.get()
  253. # django-nose test specifics
  254. TEST_RUNNER = 'desktop.lib.test_runners.HueTestRunner'
  255. # Turn off cache middleware
  256. if 'test' in sys.argv:
  257. CACHE_MIDDLEWARE_SECONDS = 0
  258. # Limit Nose coverage to Hue apps
  259. NOSE_ARGS = [
  260. '--cover-package=%s' % ','.join([app.name for app in appmanager.DESKTOP_APPS + appmanager.DESKTOP_LIBS]),
  261. '--no-path-adjustment',
  262. '--traverse-namespace'
  263. ]
  264. TIME_ZONE = desktop.conf.TIME_ZONE.get()
  265. if desktop.conf.DEMO_ENABLED.get():
  266. AUTHENTICATION_BACKENDS = ('desktop.auth.backend.DemoBackend',)
  267. else:
  268. AUTHENTICATION_BACKENDS = tuple(desktop.conf.AUTH.BACKEND.get())
  269. EMAIL_HOST = desktop.conf.SMTP.HOST.get()
  270. EMAIL_PORT = desktop.conf.SMTP.PORT.get()
  271. EMAIL_HOST_USER = desktop.conf.SMTP.USER.get()
  272. EMAIL_HOST_PASSWORD = desktop.conf.get_smtp_password()
  273. EMAIL_USE_TLS = desktop.conf.SMTP.USE_TLS.get()
  274. DEFAULT_FROM_EMAIL = desktop.conf.SMTP.DEFAULT_FROM.get()
  275. # Used for securely creating sessions. Should be unique and not shared with anybody. Changing auth backends will invalidate all open sessions.
  276. SECRET_KEY = desktop.conf.get_secret_key()
  277. if SECRET_KEY:
  278. SECRET_KEY += str(AUTHENTICATION_BACKENDS)
  279. else:
  280. import uuid
  281. SECRET_KEY = str(uuid.uuid4())
  282. # SAML
  283. SAML_AUTHENTICATION = 'libsaml.backend.SAML2Backend' in AUTHENTICATION_BACKENDS
  284. if SAML_AUTHENTICATION:
  285. from libsaml.saml_settings import *
  286. INSTALLED_APPS.append('libsaml')
  287. LOGIN_URL = '/saml2/login/'
  288. SESSION_EXPIRE_AT_BROWSER_CLOSE = True
  289. # Middleware classes.
  290. for middleware in desktop.conf.MIDDLEWARE.get():
  291. MIDDLEWARE_CLASSES.append(middleware)
  292. # OpenId
  293. OPENID_AUTHENTICATION = 'libopenid.backend.OpenIDBackend' in AUTHENTICATION_BACKENDS
  294. if OPENID_AUTHENTICATION:
  295. from libopenid.openid_settings import *
  296. INSTALLED_APPS.append('libopenid')
  297. LOGIN_URL = '/openid/login'
  298. SESSION_EXPIRE_AT_BROWSER_CLOSE = True
  299. # OAuth
  300. OAUTH_AUTHENTICATION='liboauth.backend.OAuthBackend' in AUTHENTICATION_BACKENDS
  301. if OAUTH_AUTHENTICATION:
  302. INSTALLED_APPS.append('liboauth')
  303. LOGIN_URL = '/oauth/accounts/login'
  304. SESSION_EXPIRE_AT_BROWSER_CLOSE = True
  305. # URL Redirection white list.
  306. if desktop.conf.REDIRECT_WHITELIST.get():
  307. MIDDLEWARE_CLASSES.append('desktop.middleware.EnsureSafeRedirectURLMiddleware')
  308. # Enable X-Forwarded-Host header if the load balancer requires it
  309. USE_X_FORWARDED_HOST = desktop.conf.USE_X_FORWARDED_HOST.get()
  310. # Support HTTPS load-balancing
  311. if desktop.conf.SECURE_PROXY_SSL_HEADER.get():
  312. SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
  313. ############################################################
  314. # Necessary for South to not fuzz with tests. Fixed in South 0.7.1
  315. SKIP_SOUTH_TESTS = True
  316. # Set up environment variable so Kerberos libraries look at our private
  317. # ticket cache
  318. os.environ['KRB5CCNAME'] = desktop.conf.KERBEROS.CCACHE_PATH.get()
  319. # If Hue is configured to use a CACERTS truststore, make sure that the
  320. # REQUESTS_CA_BUNDLE is set so that we can use it when we make external requests.
  321. # This is for the REST calls made by Hue with the requests library.
  322. if desktop.conf.SSL_CACERTS.get() and os.environ.get('REQUESTS_CA_BUNDLE') is None:
  323. os.environ['REQUESTS_CA_BUNDLE'] = desktop.conf.SSL_CACERTS.get()
  324. # Memory
  325. if desktop.conf.MEMORY_PROFILER.get():
  326. MEMORY_PROFILER = hpy()
  327. MEMORY_PROFILER.setrelheap()
  328. if not desktop.conf.DATABASE_LOGGING.get():
  329. def disable_database_logging():
  330. from django.db.backends import BaseDatabaseWrapper
  331. from django.db.backends.util import CursorWrapper
  332. BaseDatabaseWrapper.make_debug_cursor = lambda self, cursor: CursorWrapper(cursor, self)
  333. disable_database_logging()