settings/development.py and create_example_conf working

This commit is contained in:
Klaas van Schelven
2024-05-14 11:24:59 +02:00
parent 0863284a50
commit 3e2b6965f9
5 changed files with 78 additions and 45 deletions

3
.gitignore vendored
View File

@@ -36,3 +36,6 @@ snappea.sqlite3-wal
# node (tailwind)
node_modules
/package*
# conf
bugsink_conf.py

View File

@@ -17,7 +17,7 @@ def main():
secret_key = get_random_secret_key()
with open(args.output_file, "w") as f:
f.write('''# auto-generated example bugsink_conf.py
f.write('''from bugsink.settings.default import * # noqa
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "''' + secret_key + '''"
@@ -25,7 +25,18 @@ SECRET_KEY = "''' + secret_key + '''"
# Alternatively, pass the SECRET_KEY as an environment variable. (although that has security implications too!)
# i.e. those may leak in shared server setups.
#
# SECRET_KEY = os.getenv("SECRET_KEY")
# SECRET_KEY = os.environ["SECRET_KEY"] # use dictionary lookup rather than .getenv to ensure the variable is set.
ALLOWED_HOSTS = ["bugsink.example.org"] # set this to match your host (TODO: check what happens in forwarded configs?)
# TODO refer to database documentation and provide instructions for overrides.
# The time-zone here is the default for display purposes (when no project/user configuration is used).
# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-TIME_ZONE
TIME_ZONE = 'Europe/Amsterdam'
# See TODO in the docs
@@ -55,9 +66,11 @@ BUGSINK = {
# "BASE_URL": "http://bugsink:9000", # no trailing slash
# "SITE_TITLE": "Bugsink", # you can customize this as e.g. "My Bugsink" or "Bugsink for My Company"
}
''')
print("Configuration file created at", args.output_file)
print("Edit this file to match your setup")
# some thoughts that I haven't been able to squish into a short comment yet:
@@ -81,3 +94,6 @@ BUGSINK = {
# 3. regarding the sensitivity of this key, and storing it in the file system: I'd argue that if the server you're
# running bugsink on is compromised (and the file can be read) you have bigger problems (since the DB is also on that
# server)
if __name__ == "__main__":
main()

View File

@@ -6,8 +6,6 @@ from pathlib import Path
from django.utils.log import DEFAULT_LOGGING
from debug_toolbar.middleware import show_toolbar
# We have a single file for our default settings, and expect (if they use the recommended setup) the end-users to
# configure their setup using a single bugsink_conf.py also. To be able to have (slightly) different settings for e.g.
@@ -23,23 +21,19 @@ else:
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
BASE_DIR = Path(__file__).resolve().parent.parent.parent
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-$@clhhieazwnxnha-_zah&(bieq%yux7#^07&xsvhn58t)8@xw'
# To allow using this file without any bugsink_conf.py overrides, we get some variables from the environment. Because
# the expected use-case of this file is using the `from bugsink.settings.default import *` idiom, which implies that
# variables may very well be defined explicitly in a bugsink_conf.py or similar explicit settings file, we cannot
# enforce the existance of environment variables, so we always use os.getenv with a sane fallback.
# The fallback here is such that Django will fail to start if no SECRET_KEY is (eventually) defined, which is the goal.
SECRET_KEY = os.getenv("SECRET_KEY", "")
DEBUG = False
ALLOWED_HOSTS = ["*"] # SECURITY WARNING: also make production-worthy
INTERNAL_IPS = [
"127.0.0.1",
]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
@@ -48,10 +42,9 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'debug_toolbar',
'tailwind',
'tailwind', # As currently set up, this is also needed in production (templatetags)
'theme',
'admin_auto_filters',
'admin_auto_filters', # TODO: decide whether 'admin.py' is useful in production too.
'snappea',
'compat',
@@ -68,8 +61,6 @@ INSTALLED_APPS = [
TAILWIND_APP_NAME = 'theme'
MIDDLEWARE = [
"debug_toolbar.middleware.DebugToolbarMiddleware",
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
@@ -81,7 +72,7 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'bugsink.middleware.PerformanceStatsMiddleware',
'bugsink.middleware.PerformanceStatsMiddleware', # TODO decide whether this is useful in production too.
]
ROOT_URLCONF = 'bugsink.urls'
@@ -113,7 +104,6 @@ WSGI_APPLICATION = 'bugsink.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
@@ -121,7 +111,7 @@ DATABASES = {
'TEST': {
# Specifying a NAME here makes it so that sqlite doesn't run in-memory. This is what we want, because we
# want our tests to be as similar to the real thing as possible.
"NAME": BASE_DIR / os.getenv("DATABASE_NAME", 'test.sqlite3'),
"NAME": BASE_DIR / os.getenv("TEST_DATABASE_NAME", 'test.sqlite3'),
},
'OPTIONS': {
# the "timeout" option here is passed to the Python sqlite3.connect() translates into the busy_timeout
@@ -132,7 +122,7 @@ DATABASES = {
},
"snappea": {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / os.getenv("DATABASE_NAME", 'snappea.sqlite3'),
'NAME': BASE_DIR / os.getenv("SNAPPEA_DATABASE_NAME", 'snappea.sqlite3'),
# 'TEST': { postponed, for starters we'll do something like SNAPPEA_ALWAYS_EAGER
'OPTIONS': {
'timeout': 5,
@@ -148,7 +138,6 @@ LOGIN_REDIRECT_URL = "/"
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
@@ -166,7 +155,6 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Europe/Amsterdam'
@@ -178,7 +166,6 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / "static",
@@ -190,23 +177,13 @@ STATICFILES_DIRS = [
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
def show_toolbar_for_queryparam(request):
if "__debug__" not in request.path and not request.GET.get("debug", ""):
return False
return show_toolbar(request)
DEBUG_TOOLBAR_CONFIG = {
"SHOW_TOOLBAR_CALLBACK": show_toolbar_for_queryparam,
}
LOGGING = deepcopy(DEFAULT_LOGGING)
if I_AM_RUNNING != "TEST":
# Django's standard logging has LOGGING['handlers']['console']['filters'] = ['require_debug_true']; our app is
# configured (by default at least) to just spit everything on stdout, even in production. stdout is picked up by
# gunicorn, and we can "take it from there".
# configured (by default at least) to just spit everything on stdout, especially in production. stdout is picked up
# by e.g. gunicorn, and we can "take it from there". We don't do this when running tests, because tests are run with
# DEBUG=False and we don't want the visual pollution.
LOGGING['handlers']['console']['filters'] = []
LOGGING['loggers']['bugsink'] = {
@@ -221,14 +198,14 @@ LOGGING["formatters"]["snappea"] = {
}
LOGGING["handlers"]["snappea"] = {
"level": "DEBUG" if DEBUG else "INFO", # TODO this won't work either. but this I can do more classically (development.py)
"level": "INFO",
"class": "logging.StreamHandler"
}
LOGGING["handlers"]["snappea"]["formatter"] = "snappea"
LOGGING['loggers']['snappea'] = {
"level": "DEBUG" if DEBUG else "INFO",
"level": "INFO",
"handlers": ["snappea"],
}

View File

@@ -1,13 +1,47 @@
from .default import * # noqa
from .default import INSTALLED_APPS, MIDDLEWARE, LOGGING
import os
from debug_toolbar.middleware import show_toolbar
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
SECRET_KEY = 'django-insecure-$@clhhieazwnxnha-_zah&(bieq%yux7#^07&xsvhn58t)8@xw'
DEBUG = True
# > The Debug Toolbar is shown only if your IP address is listed in Djangos INTERNAL_IPS setting. This means that for
# > local development, you must add "127.0.0.1" to INTERNAL_IPS.
INTERNAL_IPS = [
"127.0.0.1",
]
# TODO monitor https://stackoverflow.com/questions/78476951/why-not-just-set-djangos-allowed-hosts-to
# (also for create_example_conf.py)
ALLOWED_HOSTS = ["*"]
INSTALLED_APPS += [
"debug_toolbar",
]
MIDDLEWARE = [
"debug_toolbar.middleware.DebugToolbarMiddleware",
] + MIDDLEWARE
def show_toolbar_for_queryparam(request):
if "__debug__" not in request.path and not request.GET.get("debug", ""):
return False
return show_toolbar(request)
DEBUG_TOOLBAR_CONFIG = {
"SHOW_TOOLBAR_CALLBACK": show_toolbar_for_queryparam,
}
# {PROTOCOL}://{PUBLIC_KEY}:{DEPRECATED_SECRET_KEY}@{HOST}{PATH}/{PROJECT_ID}
SENTRY_DSN = os.getenv("SENTRY_DSN")
@@ -47,3 +81,6 @@ BUGSINK = {
"BASE_URL": "http://bugsink:9000", # no trailing slash
"SITE_TITLE": "Bugsink", # you can customize this as e.g. "My Bugsink" or "Bugsink for My Company"
}
LOGGING["handlers"]["snappea"]["level"] = "DEBUG"
LOGGING["loggers"]["snappea"]["level"] = "DEBUG"

View File

@@ -6,7 +6,7 @@ import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bugsink.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bugsink.settings.development')
try:
from django.core.management import execute_from_command_line
except ImportError as exc: