Skip to content

Commit

Permalink
settings: Align with Django template
Browse files Browse the repository at this point in the history
- Configure settings according to environment variables: DEBUG and ALLOWED_HOSTS
- Add STATIC_ROOT

Internationalization:
- Add "dqt" to INSTALLED_APPS and remove LOCALE_PATHS (use default discovery instead)
- Remove LANGUAGES https://github.com/django/django/blob/stable/3.2.x/django/conf/global_settings.py
- Add django.template.context_processors.i18n to MIDDLEWARE
- Lowercase LANGUAGE_CODE

Logging:
- Abbreviate LOGGING and handle django.security.DisallowedHost
- Add ignore_logger to Sentry configuration

Security:
- Only use CORS_ALLOW_ALL_ORIGINS in development
- Add support for CSRF_COOKIE_SECURE, SESSION_COOKIE_SECURE, SECURE_* settings

Forward-compatibility:
- Add DEFAULT_AUTO_FIELD

Cleanup:
- Fix application_name for default "data" database in DATABASES
- Use pathlib for BASE_DIR
- Remove CACHE_BACKEND
  • Loading branch information
jpmckinney committed Nov 1, 2021
1 parent 604271e commit cbacaba
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 68 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -33,6 +33,8 @@ python backend/manage.py migrate

See [OCP's approach to Django settings](https://ocp-software-handbook.readthedocs.io/en/latest/python/django.html#settings). New variables are:

- `PELICAN_BACKEND_DATABASE_URL`: The [connection string](https://github.com/kennethreitz/dj-database-url#url-schema) for Pelican backend's database
- `CORS_ALLOWED_ORIGINS`: The [origins](https://github.com/adamchainz/django-cors-headers#cors_allowed_origins-sequencestr) that are authorized to make cross-site HTTP requests
- `TOKEN_PATH`: The path to a [Google `credentials.json` file](https://developers.google.com/workspace/guides/create-credentials)
- `RABBIT_URL`: The [connection string](https://pika.readthedocs.io/en/stable/examples/using_urlparameters.html#using-urlparameters) for RabbitMQ
- `RABBIT_EXCHANGE_NAME`: The name of the RabbitMQ exchange. Follow the pattern `pelican_{service}_{environment}` like `pelican_data_registry_production`
Expand Down
174 changes: 106 additions & 68 deletions backend/dqt/settings.py
@@ -1,50 +1,56 @@
"""
Django settings for dqt project.
Django settings for the project.
Generated by 'django-admin startproject' using Django 2.2.3.
Generated by "django-admin startproject" using Django 3.2.8.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
https://docs.djangoproject.com/en/3.2/ref/settings/
"""

import os
from pathlib import Path

import dj_database_url
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import ignore_logger

production = os.getenv("DJANGO_ENV") == "production"
local_access = "LOCAL_ACCESS" in os.environ or "ALLOWED_HOSTS" not in os.environ

# Build paths inside the project like this: BASE_DIR / "subdir".
BASE_DIR = Path(__file__).resolve().parent.parent

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv("SECRET_KEY", "w^pq&p1phz$^1j!aqa#8zm#m@_jhm(9skcx*8rom7x7j1cy1y=")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
DEBUG = os.getenv("DEBUG", "NO").lower() in ("on", "true", "y", "yes", "1")
DEBUG = not production

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ["*"]
ALLOWED_HOSTS = [".localhost", "127.0.0.1", "[::1]", "0.0.0.0"]
if "ALLOWED_HOSTS" in os.environ:
ALLOWED_HOSTS.extend(os.getenv("ALLOWED_HOSTS").split(","))


# Application definition
CORS_ORIGIN_ALLOW_ALL = True

INSTALLED_APPS = [
"django.contrib.admin",
# tastypie depends on django.contrib.auth
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"tastypie",
"corsheaders",
"dqt",
]

MIDDLEWARE = [
Expand All @@ -70,6 +76,7 @@
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.template.context_processors.i18n",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
Expand All @@ -79,10 +86,21 @@

WSGI_APPLICATION = "dqt.wsgi.application"

DATABASE_ROUTERS = ["dqt.routers.DbRouter"]

# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
"default": dj_database_url.config(default="postgresql:///pelican_frontend?application_name=pelican_frontend"),
# The connection string for Pelican backend's database.
"data": dj_database_url.config(
env="PELICAN_BACKEND_DATABASE_URL", default="postgresql:///pelican_backend?application_name=pelican_frontend"
),
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
Expand All @@ -101,12 +119,9 @@


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGES = [
("en", "English"),
]
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = "en-US"
LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

Expand All @@ -116,90 +131,113 @@

USE_TZ = True

LOCALE_PATHS = (BASE_DIR + "/locale",)


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = "/static/"

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"


# Project-specific Django configuration

STATIC_ROOT = BASE_DIR / "static"

# https://docs.djangoproject.com/en/3.2/topics/logging/#django-security
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"standard": {
"format": "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
"datefmt": "%d/%b/%Y %H:%M:%S",
"console": {
"format": "%(asctime)s %(levelname)s [%(name)s:%(lineno)s] %(message)s",
},
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "standard",
"formatter": "console",
},
"null": {
"class": "logging.NullHandler",
},
},
"loggers": {
"django": {
"handlers": ["console"],
"level": "INFO",
},
"django.server": {
"handlers": ["console"],
"level": "INFO",
},
"django.db.backends": {
"": {
"handlers": ["console"],
"level": "INFO",
},
"data_registry": {
"handlers": ["console"],
"level": "DEBUG",
},
"exporter": {
"handlers": ["console"],
"level": "DEBUG",
},
"cbom": {
"handlers": ["console"],
"level": "DEBUG",
},
"scrape-task": {
"handlers": ["console"],
"level": "DEBUG",
"django.security.DisallowedHost": {
"handlers": ["null"],
"propagate": False,
},
},
}

CACHE_BACKEND = "file:///tmp/dqv_backend_cache"
# https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
if production and not local_access:
# Run: env DJANGO_ENV=production SECURE_HSTS_SECONDS=1 ./manage.py check --deploy
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
SECURE_SSL_REDIRECT = True
SECURE_REFERRER_POLICY = "same-origin" # default in Django >= 3.1

# https://docs.djangoproject.com/en/3.2/ref/middleware/#http-strict-transport-security
if "SECURE_HSTS_SECONDS" in os.environ:
SECURE_HSTS_SECONDS = int(os.getenv("SECURE_HSTS_SECONDS"))
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

if os.getenv("SENTRY_DSN", False):
DATABASE_ROUTERS = ["dqt.routers.DbRouter"]


# Dependency configuration

if "SENTRY_DSN" in os.environ:
# https://docs.sentry.io/platforms/python/logging/#ignoring-a-logger
ignore_logger("django.security.DisallowedHost")
sentry_sdk.init(
dsn=os.getenv("SENTRY_DSN"),
integrations=[DjangoIntegration()],
traces_sample_rate=0, # The Sentry plan does not include Performance.
)

CORS_ORIGIN_WHITELIST = (os.getenv("CORS_ORIGIN_WHITELIST"),)
if "CORS_ALLOWED_ORIGINS" in os.environ:
CORS_ALLOWED_ORIGINS = os.getenv("CORS_ALLOWED_ORIGINS").split(",")
elif not production:
CORS_ALLOW_ALL_ORIGINS = True

TOKEN_PATH = os.getenv("TOKEN_PATH", "/data/credentials.json")

DATABASES = {
"default": dj_database_url.config(default="postgresql:///pelican_frontend?application_name=pelican_frontend"),
"data": dj_database_url.config(
env="PELICAN_BACKEND_DATABASE_URL", default="postgresql:///pelican_backend?application_name=pelican_backend"
),
# Project configuration

FATHOM = {
"domain": os.getenv("FATHOM_ANALYTICS_DOMAIN") or "cdn.usefathom.com",
"id": os.getenv("FATHOM_ANALYTICS_ID"),
}

RABBIT_URL = os.getenv("RABBIT_URL")
RABBIT_EXCHANGE_NAME = os.getenv("RABBIT_EXCHANGE_NAME")
# The path to a Google `credentials.json` file
# https://developers.google.com/workspace/guides/create-credentials
TOKEN_PATH = os.getenv("TOKEN_PATH", "credentials.json")

# The connection string for RabbitMQ.
RABBIT_URL = os.getenv("RABBIT_URL", "amqp://localhost")
# The name of the RabbitMQ exchange. Follow the pattern `pelican_{service}_{environment}`.
RABBIT_EXCHANGE_NAME = os.getenv("RABBIT_EXCHANGE_NAME", "pelican_development")

GDOCS_TEMPLATES = {
"DEFAULT_BASE_TEMPLATE": os.getenv("DEFAULT_BASE_TEMPLATE"),
"DEFAULT_DATASET_TEMPLATE": os.getenv("DEFAULT_DATASET_TEMPLATE"),
"DEFAULT_FIELD_TEMPLATE": os.getenv("DEFAULT_FIELD_TEMPLATE"),
"DEFAULT_RESOURCE_TEMPLATE": os.getenv("DEFAULT_RESOURCE_TEMPLATE"),
"DEFAULT_ERROR_TEMPLATE": os.getenv("DEFAULT_ERROR_TEMPLATE"),
# The Google Docs ID for the base template.
"DEFAULT_BASE_TEMPLATE": os.getenv("DEFAULT_BASE_TEMPLATE", "1YMG5KZCPmI6GEcd2XQktrHD8uxEL626g3uuBjLWqQlE"),
# The Google Docs ID for the field-level template.
"DEFAULT_DATASET_TEMPLATE": os.getenv("DEFAULT_DATASET_TEMPLATE", "1_1FIg3cuUthk6EEWcYnR5S-J3Xx8p1ZVDBh5oZM3eK8"),
# The Google Docs ID for the resource-level template.
"DEFAULT_FIELD_TEMPLATE": os.getenv("DEFAULT_FIELD_TEMPLATE", "1DCYMTwh_cXt-kpuxEnyKMfTlmdUoc8MwUWgbgWj7fAA"),
# The Google Docs ID for the dataset-level template.
"DEFAULT_RESOURCE_TEMPLATE": os.getenv(
"DEFAULT_RESOURCE_TEMPLATE", "1dX4md9MGOxhngjQ2Q0wY8njNiq5B6F9oFWd1tUN63TM"
),
# The Google Docs ID for the error template.
"DEFAULT_ERROR_TEMPLATE": os.getenv("DEFAULT_ERROR_TEMPLATE", "1PW7s6SmaP4tia_QzMSZkTt8Oii-6ZXqB7VCuF8bYmv4"),
}

0 comments on commit cbacaba

Please sign in to comment.