import os import sys import dj_database_url from django.utils.translation import ugettext_lazy as _ from dotenv import find_dotenv, load_dotenv # Build paths inside the project like this: os.path.join(BASE_DIR, ...) from core.env_utils import bool_value BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) load_dotenv(find_dotenv()) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get('SECRET_KEY') SIGNING_SECRET = os.environ.get('SIGNING_SECRET') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = bool_value(os.environ.get('DEBUG', '')) TEST = 'test' in sys.argv ENABLE_SILKY = bool_value(os.environ.get('ENABLE_SILKY', '')) SERVE_VIA_WEBPACK = bool_value(os.environ.get('SERVE_VIA_WEBPACK', DEBUG)) ENABLE_SENTRY = not DEBUG or bool_value(os.environ.get('ENABLE_SENTRY_DEBUG', '')) ALLOWED_HOSTS = ['*'] if not DEBUG: SECURE_SSL_REDIRECT = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # Application definition INSTALLED_APPS = [ 'core', 'api', 'users', 'books', 'objectives', 'rooms', 'assignments', 'basicknowledge', 'portfolio', 'statistics', 'surveys', 'notes', 'news', 'oauth', 'wagtail.contrib.redirects', 'wagtail.contrib.modeladmin', 'wagtail.embeds', 'wagtail.sites', 'wagtail.users', 'wagtail.snippets', 'wagtail.documents', 'wagtail.images', 'wagtail.search', 'wagtail.admin', 'wagtail.core', 'wagtail.api.v2', 'wagtailautocomplete', 'taggit', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', # 'raven.contrib.django.raven_compat', 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', 'django_filters', 'graphene_django', 'django_extensions', 'compressor', ] if DEBUG: INSTALLED_APPS += ['wagtail.contrib.styleguide'] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.middleware.gzip.GZipMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware' ] # Enable CORS for local development if DEBUG: INSTALLED_APPS += ['corsheaders'] MIDDLEWARE += ['corsheaders.middleware.CorsMiddleware'] CORS_ORIGIN_WHITELIST = ( 'http://localhost:8080', ) CORS_ALLOW_CREDENTIALS = True # enable silk for performance measuring if ENABLE_SILKY: INSTALLED_APPS += ['silk'] MIDDLEWARE += ['silk.middleware.SilkyMiddleware', ] MIDDLEWARE += [ 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'wagtail.contrib.redirects.middleware.RedirectMiddleware', 'core.middleware.ThreadLocalMiddleware', 'core.middleware.CommonRedirectMiddleware', 'core.middleware.UserLoggedInCookieMiddleWare', 'oauth.middleware.user_has_license_middleware', ] ROOT_URLCONF = 'core.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, '..', 'client/dist'), os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'core.context_processors.settings_context', ], }, }, ] WSGI_APPLICATION = 'core.wsgi.application' # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases # Database DATABASES = { 'default': dj_database_url.config(conn_max_age=600) } # Django custom user AUTH_USER_MODEL = 'users.User' # Password validation # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators WEAK_PASSWORDS = DEBUG if WEAK_PASSWORDS: AUTH_PASSWORD_VALIDATORS = [] else: AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] LOGOUT_REDIRECT_URL = '/login' LOGIN_REDIRECT_URL = '/login' LOGIN_URL = LOGIN_REDIRECT_URL # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'de' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True LANGUAGES = [ ('de', _('German')), ('en', _('English')), ] LOCALE_PATHS = [ os.path.join(BASE_DIR, 'locale') ] # Honor the 'X-Forwarded-Proto' header for request.is_secure() SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, '..', 'client/dist/static'), os.path.join(BASE_DIR, '..', 'client/src/assets'), ) if not TEST: STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' COMPRESS_CSS_FILTERS = [ # 'django_compressor_autoprefixer.AutoprefixerFilter', 'compressor.filters.cssmin.CSSMinFilter', ] STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'compressor.finders.CompressorFinder', ) COMPRESS_PRECOMPILERS = ( ('text/x-scss', 'django_libsass.SassCompiler'), ) COMPRESS_ENABLED = True if not DEBUG: COMPRESS_STORAGE = 'compressor.storage.GzipCompressorFileStorage' COMPRESS_OFFLINE = True # AWS S3 # http://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html USE_AWS = bool_value(os.environ.get('USE_AWS')) AWS_QUERYSTRING_AUTH = False AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY') AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME') AWS_S3_FILE_OVERWRITE = False # use with cloudfront AWS_S3_CUSTOM_DOMAIN = '{}.s3-{}.amazonaws.com'.format(AWS_STORAGE_BUCKET_NAME, os.environ.get('AWS_REGION', 'eu-west-1')) if USE_AWS: DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" # use with cloudfront MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN else: MEDIA_URL = '/media/' MEDIA_ROOT = os.environ.get('DJANGO_MEDIAFILES', os.path.join(BASE_DIR, 'media')) AWS_S3_OBJECT_PARAMETERS = { 'CacheControl': 'max-age=86400', } # Media Files USE_404_FALLBACK_IMAGE = bool_value(os.environ.get('USE_404_FALLBACK_IMAGE', 'True')) # Logging Conf LOGGING = { 'version': 1, 'formatters': { 'verbose_format': { 'format': '%(levelname)s %(asctime)s %(module)s %(name)s (%(process)d): %(message)s' }, 'simple_format': { 'format': '%(levelname)s %(name)s: %(message)s' }, }, 'disable_existing_loggers': True, 'handlers': { 'mail_admins': { 'level': 'CRITICAL', 'class': 'django.utils.log.AdminEmailHandler' }, 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'stream': sys.stdout, 'formatter': 'simple_format' }, # for automatic papertrail logging 'SysLog': { 'level': 'INFO', 'class': 'logging.handlers.SysLogHandler', 'formatter': 'simple_format', }, }, 'loggers': { '': { 'handlers': ['console'], 'level': 'WARNING' }, 'skillbox': { 'handlers': ['console', 'SysLog'], 'level': 'DEBUG', 'propagate': False }, 'graphql': { 'handlers': ['console'], 'level': 'WARNING', 'propagate': False }, 'django': { 'handlers': ['console'], 'level': 'WARNING' }, 'django.server': { 'handlers': ['console'], 'level': 'WARNING', 'propagate': True, }, } } if ENABLE_SENTRY and os.environ.get('SENTRY_DSN'): import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration def before_send(event, hint): user = event['user'] id = user['id'] event['user'] = {'id': id} return event environment = os.environ.get('SENTRY_ENV', 'localhost') sentry_sdk.init( dsn=os.environ.get('SENTRY_DSN'), integrations=[DjangoIntegration()], send_default_pii=True, before_send=before_send, environment=environment ) RAVEN_DSN_JS = os.environ.get('RAVEN_DSN_JS', '') GRAPHENE = { 'SCHEMA': 'api.schema.schema', 'SCHEMA_OUTPUT': 'schema.graphql' } # if DEBUG: # GRAPHENE['MIDDLEWARE'] = [ # 'graphene_django.debug.DjangoDebugMiddleware', # ] # http://docs.wagtail.io/en/v2.1/advanced_topics/settings.html?highlight=urls WAGTAIL_SITE_NAME = 'skillbox' WAGTAILSEARCH_BACKENDS = { 'default': { 'BACKEND': 'wagtail.search.backends.database', } } WAGTAILDOCS_DOCUMENT_MODEL = 'books.CustomDocument' GRAPHQL_QUERIES_DIR = os.path.join(BASE_DIR, '..', 'client', 'src', 'graphql', 'gql', 'queries') GRAPHQL_MUTATIONS_DIR = os.path.join(GRAPHQL_QUERIES_DIR, '../mutations') DEFAULT_FROM_EMAIL = 'myskillbox ' # Metanet Config if DEBUG: EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' else: EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' ALLOW_BETA_LOGIN = True # HEP HEP_URL = os.environ.get("HEP_URL") # HEP Oauth AUTHLIB_OAUTH_CLIENTS = { 'hep': { 'client_id': os.environ.get("OAUTH_CLIENT_ID"), 'client_secret': os.environ.get("OAUTH_CLIENT_SECRET"), 'request_token_url': None, 'request_token_params': None, 'access_token_url': os.environ.get("OAUTH_ACCESS_TOKEN_URL"), 'access_token_params': None, 'refresh_token_url': None, 'authorize_url': os.environ.get("OAUTH_AUTHORIZE_URL"), 'api_base_url': os.environ.get("OAUTH_API_BASE_URL"), 'client_kwargs': { 'scope': 'orders', 'token_endpoint_auth_method': 'client_secret_post', 'token_placement': 'header', } } } PLATFORM = os.environ.get('APP_FLAVOR', 'myskillbox') OAUTH_LOCAL_REDIRECT_URI = os.environ.get("OAUTH_LOCAL_REDIRECT_URI") TASKBASE_USER = os.environ.get("TASKBASE_USER") TASKBASE_PASSWORD = os.environ.get("TASKBASE_PASSWORD") TASKBASE_SUPERUSER = os.environ.get("TASKBASE_SUPERUSER") TASKBASE_SUPERPASSWORD = os.environ.get("TASKBASE_SUPERPASSWORD") TASKBASE_BASEURL = os.environ.get("TASKBASE_BASEURL") ENABLE_SPELLCHECK = True if TASKBASE_BASEURL else False TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' TEST_OUTPUT_DIR = './test-reports/' TEST_OUTPUT_VERBOSE = 1 # new default in Django 3.0, making it explicit to facilitate bug hunting X_FRAME_OPTIONS = 'DENY' SECURE_CONTENT_TYPE_NOSNIFF = True # Django 3.2 uses BitAutoField by default, we keep things the old way DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'