From 0b6e2ab2fb1789380e5f20b270bde60f8c5f29e9 Mon Sep 17 00:00:00 2001 From: Mike Graves Date: Tue, 26 Nov 2019 12:11:16 -0500 Subject: [PATCH] Add python-dotenv to manage.py This partially addresses #177. Completely fixing this issue is going to require much deeper work, I think, and will be better addressed across multiple PRs. --- Pipfile | 1 + Pipfile.lock | 26 +++++++++++------- manage.py | 4 +++ solenoid/settings/base.py | 56 +++++++++++++++++++++++++++------------ 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/Pipfile b/Pipfile index 5f300f2..9b9c9cc 100644 --- a/Pipfile +++ b/Pipfile @@ -35,3 +35,4 @@ Pillow = "*" sentry-sdk = "*" celery = "*" redis = "*" +python-dotenv = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 2e57f46..0f1ccb8 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "59c3cbea877917a5bac2566032ad8430571da8ec66ea7790612ff38aaf548624" + "sha256": "ef1dbcc3a5488ee42df4e6d5d1b14857c9c69f4aebf12f1adb8bbbb29b58a325" }, "pipfile-spec": 6, "requires": { @@ -142,11 +142,11 @@ }, "gunicorn": { "hashes": [ - "sha256:0806b5e8a2eb8ba9ac1be65d7b743ec896fc25f5d6cb16c5e051540157b315bb", - "sha256:ef69dea4814df95e64e3f40b47b7ffedc6911c5009233be9d01cfd0d14aa3f50" + "sha256:1d8012b859f4cd9e45753f1ccb33a94df1ab9e1b7af4f81ac871680b4042b08b", + "sha256:5c6f119298dd692ba49d83ea351aeefdb63d33e32179d91d173d942525115890" ], "index": "pypi", - "version": "==20.0.0" + "version": "==20.0.3" }, "idna": { "hashes": [ @@ -199,10 +199,10 @@ }, "newrelic": { "hashes": [ - "sha256:185833654753b9b54a8314edb067294e184600a7ca0e45b0201402a12cbfdd5a" + "sha256:d0e69703792f5abb7ea2440bbbcaa560892c364a09df60bdf36db77f95124f7b" ], "index": "pypi", - "version": "==5.2.3.131" + "version": "==5.4.0.132" }, "oauthlib": { "hashes": [ @@ -273,6 +273,14 @@ ], "version": "==1.7.1" }, + "python-dotenv": { + "hashes": [ + "sha256:debd928b49dbc2bf68040566f55cdb3252458036464806f4094487244e2a4093", + "sha256:f157d71d5fec9d4bd5f51c82746b6344dffa680ee85217c123f4a0c8117c4544" + ], + "index": "pypi", + "version": "==0.10.3" + }, "python3-openid": { "hashes": [ "sha256:0086da6b6ef3161cfe50fb1ee5cceaf2cda1700019fda03c2c5c440ca6abe4fa", @@ -357,11 +365,11 @@ }, "sentry-sdk": { "hashes": [ - "sha256:09e1e8f00f22ea580348f83bbbd880adf40b29f1dec494a8e4b33e22f77184fb", - "sha256:ff1fa7fb85703ae9414c8b427ee73f8363232767c9cd19158f08f6e4f0b58fc7" + "sha256:a7c2c8d3f53b6b57454830cd6a4b73d272f1ba91952f59e6545b3cf885f3c22f", + "sha256:bfc486af718c268cf49ff43d6334ed4db7333ace420240b630acdd8f8a3a8f60" ], "index": "pypi", - "version": "==0.13.2" + "version": "==0.13.4" }, "six": { "hashes": [ diff --git a/manage.py b/manage.py index 4d1be29..873db57 100755 --- a/manage.py +++ b/manage.py @@ -2,7 +2,11 @@ import os import sys +from dotenv import load_dotenv + + if __name__ == "__main__": + load_dotenv() os.environ.setdefault("DJANGO_SETTINGS_MODULE", "solenoid.settings.base") from django.core.management import execute_from_command_line diff --git a/solenoid/settings/base.py b/solenoid/settings/base.py index a23906c..466cb58 100644 --- a/solenoid/settings/base.py +++ b/solenoid/settings/base.py @@ -11,11 +11,38 @@ """ import os +import dj_database_url from django.urls import reverse_lazy BASE_DIR = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +def boolean(value): + """Turn the given string value into a boolean. + + Any truthy value will be interpreted as True and anything else will + be False. For convenience, this function will also accept a boolean + value (and simply return it) and the value None, which will be + interpreted as False. + """ + if isinstance(value, bool) or value is None: + return bool(value) + return value.lower() in ('true', 't', 'yes', 'y', '1') + + +def make_list(value): + """Return a list of items from a comma-separated string. + + Surrounding whitespace will be stripped from the list items. If the + provided string is empty, an empty list will be returned. This function + will also accept the value None and return an empty list. + """ + if value is None: + return [] + return list(filter(None, [s.strip() for s in value.split(',')])) + + # ----------------------------------------------------------------------------- # ------------------------> core django configurations <----------------------- # ----------------------------------------------------------------------------- @@ -60,15 +87,7 @@ # DEBUG # ----------------------------------------------------------------------------- -# By setting this an an environment variable, it is easy to switch debug on in -# servers to do a quick test. -# DEBUG SHOULD BE FALSE ON PRODUCTION for security reasons. -PROTO_DEBUG = os.environ.get('DJANGO_DEBUG') - -if PROTO_DEBUG == 'True' or PROTO_DEBUG is True: - DEBUG = True -else: - DEBUG = False +DEBUG = boolean(os.getenv('DEBUG', False)) # DATABASE CONFIGURATION # ----------------------------------------------------------------------------- @@ -76,10 +95,9 @@ # https://docs.djangoproject.com/en/1.8/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } + 'default': dj_database_url.config( + default=os.getenv('DATABASE_URL', 'sqlite:///db.sqlite3'), + conn_max_age=600) } @@ -87,11 +105,14 @@ # ----------------------------------------------------------------------------- # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '_c+yx&rwl@mg$c()!p+78($if4uqa^p$czhl-tl$)*1v5#xus0' +SECRET_KEY = os.environ['DJANGO_SECRET_KEY'] + +# This will accept a comma-separated list of allowed hosts +ALLOWED_HOSTS = make_list(os.getenv('ALLOWED_HOSTS')) -# In production, this list should contain the URL of the server and nothing -# else, for security reasons. For local testing '*' is OK. -ALLOWED_HOSTS = ['*'] +if 'HEROKU_APP_NAME' in os.environ: + ALLOWED_HOSTS.append( + '{}.herokuapp.com'.format(os.environ['HEROKU_APP_NAME'])) ROOT_URLCONF = 'solenoid.urls' @@ -99,6 +120,7 @@ SITE_ID = 1 +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # INTERNATIONALIZATION CONFIGURATION # -----------------------------------------------------------------------------