diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..3ba24ff Binary files /dev/null and b/.DS_Store differ diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..54cdb12 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.git +.venv +node_modules +staticfiles +media +db.sqlite3 +.env +*.pyc +__pycache__ +.coverage +.idea +.ruff_cache +ARCHITECTURE.pdf diff --git a/.env.compose.example b/.env.compose.example new file mode 100644 index 0000000..247d84c --- /dev/null +++ b/.env.compose.example @@ -0,0 +1,10 @@ +# Copy to .env — read by docker compose itself (not by Django). +ROSTERCHIEF_BASE_DOMAIN=rosterchief.app +ACME_EMAIL=you@example.com + +# DNS-01 is the only way to get the *.rosterchief.app wildcard. Token needs DNS:Edit on the zone. +CLOUDFLARE_API_TOKEN= + +POSTGRES_DB=rosterchief +POSTGRES_USER=rosterchief +POSTGRES_PASSWORD= diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..746e21e --- /dev/null +++ b/.env.example @@ -0,0 +1,37 @@ +# Copy to .env and fill in. Values below are development-friendly defaults. + +# Required. Generate one, e.g. `python -c "import secrets; print(secrets.token_urlsafe(50))"`. +DJANGO_SECRET_KEY=change-me + +# Development toggles. +DJANGO_DEBUG=True + +# Hosts Django will serve. `.localhost` matches localhost and any *.localhost +# subdomain, which the tenant middleware needs for per-club subdomains. +DJANGO_ALLOWED_HOSTS=.localhost,127.0.0.1,[::1] + +# Multi-tenancy: subdomains of this base domain resolve to a club by slug, +# e.g. http://ajax-united.localhost:8000/ -> club with slug "ajax-united". +# In production set this to your real base domain (e.g. rosterchief.app). +ROSTERCHIEF_BASE_DOMAIN=localhost + +# Two-factor auth. ROSTERCHIEF_BASE_DOMAIN doubles as the WebAuthn Relying Party +# ID, so ONE passkey works across every club subdomain. Change it and existing +# passkeys stop validating -- they are cryptographically bound to that domain. +# ROSTERCHIEF_RP_NAME is what the browser shows during a passkey prompt. +# ROSTERCHIEF_RP_NAME=RosterChief + +# Sessions are shared across club subdomains (log in once, all clubs). Derived +# from ROSTERCHIEF_BASE_DOMAIN in production; left host-only on localhost +# because browsers reject a Domain attribute there. Override if needed. +# DJANGO_SESSION_COOKIE_DOMAIN=.rosterchief.app +# DJANGO_CSRF_COOKIE_DOMAIN=.rosterchief.app + +# Optional. Defaults to sqlite:///db.sqlite3 for dev; point at Postgres in prod. +# DJANGO_DATABASE_URL=postgres://user:pass@localhost:5432/rosterchief + +# Optional. CSRF trusted origins (needed for subdomains in prod), comma-separated. +# DJANGO_CSRF_TRUSTED_ORIGINS=https://*.rosterchief.app + +# Optional. +# DJANGO_TIME_ZONE=Europe/Brussels diff --git a/.env.production.example b/.env.production.example new file mode 100644 index 0000000..5a86d9b --- /dev/null +++ b/.env.production.example @@ -0,0 +1,38 @@ +# Copy to .env.production and fill in. Everything here is read by python-decouple. + +# --- Django --- +DJANGO_SECRET_KEY= # python -c "import secrets; print(secrets.token_urlsafe(64))" +DJANGO_DEBUG=False +# The leading dot matches every club subdomain. +DJANGO_ALLOWED_HOSTS=.rosterchief.app +DJANGO_CSRF_TRUSTED_ORIGINS=https://rosterchief.app,https://*.rosterchief.app +DJANGO_TIME_ZONE=Europe/Brussels + +# --- Tenancy --- +# Drives subdomain resolution, the shared session cookie, and the WebAuthn RP ID (one passkey +# across every club). +ROSTERCHIEF_BASE_DOMAIN=rosterchief.app +ROSTERCHIEF_RP_NAME=RosterChief + +# --- Services --- +DJANGO_DATABASE_URL=postgres://rosterchief:CHANGEME@db:5432/rosterchief +DJANGO_REDIS_URL=redis://redis:6379/0 + +# --- HTTPS (off by default in code; the deploy is what turns them on) --- +DJANGO_SECURE_SSL_REDIRECT=True +DJANGO_SESSION_COOKIE_SECURE=True +DJANGO_CSRF_COOKIE_SECURE=True +DJANGO_SECURE_HSTS_SECONDS=31536000 +DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS=True +# Preload is a one-way door — turn it on only once the wildcard cert has proven itself. +DJANGO_SECURE_HSTS_PRELOAD=False + +# --- Static --- +DJANGO_STATICFILES_BACKEND=whitenoise.storage.CompressedManifestStaticFilesStorage + +# --- Uploads: set these and club logos move off local disk (required for >1 app server) --- +# AWS_STORAGE_BUCKET_NAME=rosterchief-media +# AWS_S3_ENDPOINT_URL=https://fsn1.your-objectstorage.com +# AWS_S3_REGION_NAME=fsn1 +# AWS_ACCESS_KEY_ID= +# AWS_SECRET_ACCESS_KEY= diff --git a/.gitignore b/.gitignore index d0fee72..b987436 100644 --- a/.gitignore +++ b/.gitignore @@ -376,6 +376,7 @@ poetry.toml # LSP config files pyrightconfig.json +# End of https://www.toptal.com/developers/gitignore/api/python,pycharm,django% +# Node node_modules/ - -# End of https://www.toptal.com/developers/gitignore/api/python,pycharm,django% \ No newline at end of file +staticfiles/ diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..e3a051f --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:$PROJECT_DIR$/db.sqlite3 + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/markdown.xml b/.idea/markdown.xml new file mode 100644 index 0000000..00405d5 --- /dev/null +++ b/.idea/markdown.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index d8e05c0..34d3806 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/pyLspTools.xml b/.idea/pyLspTools.xml index e746c6c..f39483f 100644 --- a/.idea/pyLspTools.xml +++ b/.idea/pyLspTools.xml @@ -13,4 +13,7 @@ + + \ No newline at end of file diff --git a/.idea/pySourceRootDetection.xml b/.idea/pySourceRootDetection.xml new file mode 100644 index 0000000..089a2ac --- /dev/null +++ b/.idea/pySourceRootDetection.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/ClubManager.iml b/.idea/rosterchief.iml similarity index 73% rename from .idea/ClubManager.iml rename to .idea/rosterchief.iml index 1c9d6d4..f20c0e6 100644 --- a/.idea/ClubManager.iml +++ b/.idea/rosterchief.iml @@ -4,7 +4,7 @@