From a3df1d70949f6e572940724ef8c12af591852ef6 Mon Sep 17 00:00:00 2001 From: Ben Sturmfels Date: Wed, 20 Mar 2024 13:29:37 +1100 Subject: [PATCH] Switch settings to use "the one true way" approach The advantage of this approach is that the production and dev configurations are in version control, so there's less opportunity for surprises. As advocated by Jacob Kaplan-Moss (OSCON 2011) and Two Scoops of Django book. --- .gitignore | 1 + Dockerfile-debian-bookworm | 3 -- README.md | 4 -- TODO.md | 4 +- conservancy/local_context_processors.py | 3 +- conservancy/settings/__init__.py | 0 conservancy/{settings.py => settings/base.py} | 6 +-- conservancy/settings/dev.py | 17 ++++++++ conservancy/settings/prod.py | 41 +++++++++++++++++++ manage.py | 2 +- 10 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 conservancy/settings/__init__.py rename conservancy/{settings.py => settings/base.py} (96%) create mode 100644 conservancy/settings/dev.py create mode 100644 conservancy/settings/prod.py diff --git a/.gitignore b/.gitignore index 8dd72393..405e2499 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ conservancy/static/docs/SFC_response_to_summary_judgement.pdf conservancy/static/docs/Vizio_summary_judgement_reply_brief.pdf conservancy/static/docs/2023-4-28 VIZIOs Motion for Summary Judgment with Reservation.pdf +/conservancy/secrets.json diff --git a/Dockerfile-debian-bookworm b/Dockerfile-debian-bookworm index 446a27f0..b47896d0 100644 --- a/Dockerfile-debian-bookworm +++ b/Dockerfile-debian-bookworm @@ -1,9 +1,6 @@ # To build the Docker image with the necessary dependencies: # docker build --tag sfconservancy.org-bookworm --file Dockerfile-debian-bookworm . # -# To run the website, first ensure you have a -# "conservancy/djangocommonsettings.py" file, with an appropriate database path. -# # [FIRST RUN ONLY] If you don't have an existing copy of the database, run: # touch conservancy-website.sqlite3 # diff --git a/README.md b/README.md index e2ca086a..3cc13799 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,6 @@ Debian: python3 -m pip install -r requirements.txt -You'll need a copy of `conservancy/djangocommonsettings.py`, a file that not -committed to the repository that has database settings and other -environment-specific config. - To run the tests, install `pytest-django` and run pytest: python3 -m pip install pytest-django diff --git a/TODO.md b/TODO.md index 0ee08db4..a2b33aa4 100644 --- a/TODO.md +++ b/TODO.md @@ -5,12 +5,12 @@ * use `` elements for supporter page hidden sections, rather than complex jQuery - or consider Alpine.js * replace `internalNavigate` with inline flexbox layout * add tests for main pages returning 200 -* standardise settings to replace `settings.py` and `djangocommonsettings.py` - with `settings/prod.py` and move `SECRET_KEY` to an environment variable # Done +* standardise settings to replace `settings.py` and `djangocommonsettings.py` + with `settings/prod.py` and move `SECRET_KEY` to an environment variable * migrate to Django 4.2 LTS * review `apache2` directory - may be unused * add deployment script that runs migrations and collects static files diff --git a/conservancy/local_context_processors.py b/conservancy/local_context_processors.py index 5cfd9869..9e9499e1 100644 --- a/conservancy/local_context_processors.py +++ b/conservancy/local_context_processors.py @@ -1,6 +1,7 @@ from datetime import datetime as DateTime -from . import settings +from django.conf import settings + from .fundgoal.models import FundraisingGoal SITE_FUNDGOAL = 'cy2023-end-year-match' diff --git a/conservancy/settings/__init__.py b/conservancy/settings/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/conservancy/settings.py b/conservancy/settings/base.py similarity index 96% rename from conservancy/settings.py rename to conservancy/settings/base.py index 6440570f..611ce1a0 100644 --- a/conservancy/settings.py +++ b/conservancy/settings/base.py @@ -19,13 +19,9 @@ from pathlib import Path -from .djangocommonsettings import * - SITE_ID = 2 ROOT_URLCONF = 'conservancy.urls' -FORCE_CANONICAL_HOSTNAME = False if DEBUG else 'sfconservancy.org' - REDIRECT_TABLE = { 'www.sf-conservancy.org': 'sfconservancy.org', } @@ -101,7 +97,7 @@ INSTALLED_APPS = [ DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' -BASE_DIR = Path(__file__).resolve().parent +BASE_DIR = Path(__file__).resolve().parent.parent TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', diff --git a/conservancy/settings/dev.py b/conservancy/settings/dev.py new file mode 100644 index 00000000..b77d2d07 --- /dev/null +++ b/conservancy/settings/dev.py @@ -0,0 +1,17 @@ +from .base import * + +DEBUG = True +ALLOWED_HOSTS = ['*'] + +FORCE_CANONICAL_HOSTNAME = False + +DATABASES = { + 'default': { + 'NAME': 'conservancy-website.sqlite3', + 'ENGINE': 'django.db.backends.sqlite3', + } +} + +SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/conservancy/settings/prod.py b/conservancy/settings/prod.py new file mode 100644 index 00000000..e1c97300 --- /dev/null +++ b/conservancy/settings/prod.py @@ -0,0 +1,41 @@ +import json + +from django.core.exceptions import ImproperlyConfigured + +from .base import * + +DEBUG = False +ALLOWED_HOSTS = ['www.sfconservancy.org', 'sfconservancy.org'] + +FORCE_CANONICAL_HOSTNAME = 'sfconservancy.org' + +ADMINS = [ + ('Bradley M. Kuhn', 'sysadmin@sfconservancy.org'), + ('Ben Sturmfels', 'sysadmin+conservancy@sturm.com.au'), +] + +MANAGERS = [ + ('Bradley M. Kuhn', 'sysadmin@sfconservancy.org'), +] + +DATABASES = { + 'default': { + 'NAME': '/var/lib/www/database/conservancy-website.sqlite3', + 'ENGINE': 'django.db.backends.sqlite3', + } +} + +# Apache/mod_wsgi doesn't make it straightforward to pass environment variables +# to Django (can't use the Apache config). +with open(BASE_DIR / 'secrets.json') as f: + secrets = json.load(f) + +def get_secret(secrets, setting): + try: + return secrets[setting] + except KeyError: + raise ImproperlyConfigured(f'Missing secret \'{setting}\'') + +SECRET_KEY = get_secret(secrets, 'SECRET_KEY') + +SESSION_COOKIE_SECURE = True diff --git a/manage.py b/manage.py index acbc9732..c3f44dca 100755 --- a/manage.py +++ b/manage.py @@ -7,7 +7,7 @@ import os import sys if __name__ == '__main__': - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conservancy.settings') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conservancy.settings.dev') try: from django.core.management import execute_from_command_line except ImportError as exc: