summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--core/config.py21
-rw-r--r--core/context.py4
-rw-r--r--docker/Dockerfile (renamed from Dockerfile)9
-rw-r--r--docker/docker-compose.yml (renamed from docker-compose.yml)2
-rw-r--r--docker/start.sh (renamed from scripts/start.sh)0
-rwxr-xr-xmanage.py2
-rw-r--r--requirements.txt1
-rw-r--r--setup.cfg2
-rw-r--r--takahe/asgi.py2
-rw-r--r--takahe/settings/__init__.py0
-rw-r--r--takahe/settings/base.py (renamed from takahe/settings.py)20
-rw-r--r--takahe/settings/development.py13
-rw-r--r--takahe/settings/production.py17
-rw-r--r--takahe/settings/testing.py4
-rw-r--r--takahe/wsgi.py2
-rw-r--r--users/views/identity.py4
17 files changed, 75 insertions, 32 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b87b2ce
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+.PHONY: clean
+
+image:
+ docker build -t takahe -f docker/Dockerfile .
diff --git a/core/config.py b/core/config.py
index 0f09404..b9f6878 100644
--- a/core/config.py
+++ b/core/config.py
@@ -1,3 +1,20 @@
-class Config:
+import pydantic
- pass
+
+class Config(pydantic.BaseModel):
+
+ # Basic configuration options
+ site_name: str = "takahē"
+ identity_max_age: int = 24 * 60 * 60
+
+ # Cached ORM object storage
+ __singleton__ = None
+
+ class Config:
+ env_prefix = "takahe_"
+
+ @classmethod
+ def load(cls) -> "Config":
+ if cls.__singleton__ is None:
+ cls.__singleton__ = cls()
+ return cls.__singleton__
diff --git a/core/context.py b/core/context.py
index 026ac11..17617b9 100644
--- a/core/context.py
+++ b/core/context.py
@@ -1,7 +1,7 @@
-from django.conf import settings
+from core.config import Config
def config_context(request):
return {
- "config": {"site_name": settings.SITE_NAME},
+ "config": Config.load(),
}
diff --git a/Dockerfile b/docker/Dockerfile
index 1f62240..14e033b 100644
--- a/Dockerfile
+++ b/docker/Dockerfile
@@ -1,4 +1,6 @@
-FROM python:3.9-bullseye as builder
+# Build stage
+
+FROM python:3.11.0-buster as builder
RUN mkdir -p /takahe
RUN python -m venv /takahe/.venv
@@ -12,8 +14,9 @@ RUN . /takahe/.venv/bin/activate \
&& pip install --upgrade pip \
&& pip install --upgrade -r requirements.txt
+# Final image stage
-FROM python:3.9-slim-bullseye
+FROM python:3.11.0-slim-buster
RUN apt-get update && apt-get install -y libpq5
@@ -23,4 +26,4 @@ COPY . /takahe
WORKDIR /takahe
EXPOSE 8000
-CMD ["/takahe/scripts/start.sh"]
+CMD ["/takahe/docker/start.sh"]
diff --git a/docker-compose.yml b/docker/docker-compose.yml
index f64bfb6..00463bf 100644
--- a/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -19,7 +19,7 @@ services:
build: .
image: tahake:latest
environment:
- - "DJANGO_SETTINGS_MODULE=takahe.settings"
+ - "DJANGO_SETTINGS_MODULE=takahe.settings.production"
- "SECRET_KEY=insecure_secret"
- "POSTGRES_HOST=db"
- "POSTGRES_DB=tahake"
diff --git a/scripts/start.sh b/docker/start.sh
index 99f1ed0..99f1ed0 100644
--- a/scripts/start.sh
+++ b/docker/start.sh
diff --git a/manage.py b/manage.py
index 21eb71e..3985c18 100755
--- a/manage.py
+++ b/manage.py
@@ -6,7 +6,7 @@ import sys
def main():
"""Run administrative tasks."""
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "takahe.settings")
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "takahe.settings.production")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
diff --git a/requirements.txt b/requirements.txt
index dbe6fb0..e897cfc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,3 +12,4 @@ psycopg2~=2.9.5
bleach~=5.0.1
pytest-django~=4.5.2
pytest-httpx~=0.21
+pydantic~=1.10.2
diff --git a/setup.cfg b/setup.cfg
index f70f6f1..a2e3e8f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -9,7 +9,7 @@ multi_line_output = 3
[tool:pytest]
addopts = --tb=short
-DJANGO_SETTINGS_MODULE = takahe.settings
+DJANGO_SETTINGS_MODULE = takahe.settings.testing
filterwarnings =
ignore:There is no current event loop
diff --git a/takahe/asgi.py b/takahe/asgi.py
index 99a9cfb..3424b23 100644
--- a/takahe/asgi.py
+++ b/takahe/asgi.py
@@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "takahe.settings")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "takahe.settings.production")
application = get_asgi_application()
diff --git a/takahe/settings/__init__.py b/takahe/settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/takahe/settings/__init__.py
diff --git a/takahe/settings.py b/takahe/settings/base.py
index e8982ae..a2ccb98 100644
--- a/takahe/settings.py
+++ b/takahe/settings/base.py
@@ -1,17 +1,7 @@
import os
from pathlib import Path
-# Build paths inside the project like this: BASE_DIR / 'subdir'.
-BASE_DIR = Path(__file__).resolve().parent.parent
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = os.environ.get("SECRET_KEY", "insecure_secret")
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-
-ALLOWED_HOSTS = ["*"]
-CSRF_TRUSTED_ORIGINS = ["http://*", "https://*"]
+BASE_DIR = Path(__file__).resolve().parent.parent.parent
# Application definition
@@ -30,7 +20,6 @@ INSTALLED_APPS = [
]
MIDDLEWARE = [
- "core.middleware.AlwaysSecureMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
@@ -115,9 +104,4 @@ STATICFILES_DIRS = [
BASE_DIR / "static",
]
-CRISPY_FAIL_SILENTLY = not DEBUG
-
-SITE_NAME = "takahē"
-DEFAULT_DOMAIN = "feditest.aeracode.org"
-ALLOWED_DOMAINS = ["feditest.aeracode.org"]
-IDENTITY_MAX_AGE = 24 * 60 * 60
+ALLOWED_HOSTS = ["*"]
diff --git a/takahe/settings/development.py b/takahe/settings/development.py
new file mode 100644
index 0000000..4e0098b
--- /dev/null
+++ b/takahe/settings/development.py
@@ -0,0 +1,13 @@
+import os
+
+from .base import * # noqa
+
+# Load secret key from environment with a fallback
+SECRET_KEY = os.environ.get("TAKAHE_SECRET_KEY", "insecure_secret")
+
+# Disable the CRSF origin protection
+MIDDLEWARE.insert(0, "core.middleware.AlwaysSecureMiddleware")
+
+# Ensure debug features are on
+DEBUG = True
+CRISPY_FAIL_SILENTLY = False
diff --git a/takahe/settings/production.py b/takahe/settings/production.py
new file mode 100644
index 0000000..2f943f4
--- /dev/null
+++ b/takahe/settings/production.py
@@ -0,0 +1,17 @@
+import os
+
+from .base import * # noqa
+
+# Load secret key from environment
+try:
+ SECRET_KEY = os.environ["TAKAHE_SECRET_KEY"]
+except KeyError:
+ print("You must specify the TAKAHE_SECRET_KEY environment variable!")
+ os._exit(1)
+
+# Ensure debug features are off
+DEBUG = False
+CRISPY_FAIL_SILENTLY = True
+
+# TODO: Allow better setting of allowed_hosts, if we need to
+ALLOWED_HOSTS = ["*"]
diff --git a/takahe/settings/testing.py b/takahe/settings/testing.py
new file mode 100644
index 0000000..6527333
--- /dev/null
+++ b/takahe/settings/testing.py
@@ -0,0 +1,4 @@
+from .base import * # noqa
+
+# Fixed secret key
+SECRET_KEY = "testing_secret"
diff --git a/takahe/wsgi.py b/takahe/wsgi.py
index 05ae06f..c8ad0a0 100644
--- a/takahe/wsgi.py
+++ b/takahe/wsgi.py
@@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "takahe.settings")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "takahe.settings.production")
application = get_wsgi_application()
diff --git a/users/views/identity.py b/users/views/identity.py
index 5d11d63..d78bda1 100644
--- a/users/views/identity.py
+++ b/users/views/identity.py
@@ -1,13 +1,13 @@
import string
from django import forms
-from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views.generic import FormView, TemplateView, View
+from core.config import Config
from core.forms import FormHelper
from users.decorators import identity_required
from users.models import Domain, Follow, Identity, IdentityStates
@@ -26,7 +26,7 @@ class ViewIdentity(TemplateView):
fetch=True,
)
posts = identity.posts.all()[:100]
- if identity.data_age > settings.IDENTITY_MAX_AGE:
+ if identity.data_age > Config.load().IDENTITY_MAX_AGE:
identity.transition_perform(IdentityStates.outdated)
return {
"identity": identity,