Harden auth, AI tutor, payments, and subscriptions
This commit is contained in:
118
config/tests.py
Normal file
118
config/tests.py
Normal file
@@ -0,0 +1,118 @@
|
||||
import importlib
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
class SecretKeyFailClosedTests(SimpleTestCase):
|
||||
"""
|
||||
تستهای متمرکز روی این فیکس: SECRET_KEY دیگه در پروداکشن (DEBUG=False)
|
||||
دیفالتِ هاردکد/قابلحدسزدن نداره. اگه DJANGO_SECRET_KEY ست نشده باشه،
|
||||
settings.py باید fail-closed بشه (خطای صریح موقعِ import)، نه اینکه با
|
||||
یک fallback شناختهشده بالا بیاد. برای DEBUG=True، fallbackِ محلیِ قبلی
|
||||
باید دستنخورده بمونه.
|
||||
|
||||
مثل SecretDefaultsFailClosedTests در payment/tests.py، چون SECRET_KEY
|
||||
فقط یکبار موقعِ import محاسبه میشه (نه چیزی که override_settings
|
||||
بتونه toggle کنه)، ماژولِ config.settings رو با متغیرهای محیطیِ
|
||||
کنترلشده reload میکنیم.
|
||||
"""
|
||||
|
||||
allow_database_queries = True
|
||||
|
||||
def _reload_settings_with_env(self, env_overrides, env_removed=()):
|
||||
from config import settings as settings_module
|
||||
|
||||
clean_env = {k: v for k, v in os.environ.items() if k not in env_removed}
|
||||
clean_env.update(env_overrides)
|
||||
with patch.dict(os.environ, clean_env, clear=True):
|
||||
importlib.reload(settings_module)
|
||||
return settings_module
|
||||
|
||||
def tearDown(self):
|
||||
# همیشه ماژول رو به حالتِ واقعیِ محیطِ تست برمیگردونیم تا روی
|
||||
# بقیهی تستها اثر نذاره.
|
||||
from config import settings as settings_module
|
||||
importlib.reload(settings_module)
|
||||
|
||||
def test_production_missing_secret_key_fails_closed(self):
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
self._reload_settings_with_env(
|
||||
env_overrides={'DJANGO_DEBUG': ''},
|
||||
env_removed={'DJANGO_SECRET_KEY'},
|
||||
)
|
||||
|
||||
def test_production_configured_secret_key_used(self):
|
||||
# ⚠️ اصلاح (باگِ خودِ تست، نه اپلیکیشن): این تست فقط رفتارِ
|
||||
# SECRET_KEY رو میسنجه، اما چون CACHE_URL رو ست نمیکرد، وقتی
|
||||
# فیکسِ جداگانهی CACHE_URL fail-closed (پایینترِ همین فایل، نگاه
|
||||
# کنید به CacheUrlFailClosedTests) اضافه شد، همین import/reload با
|
||||
# DEBUG=False و بدونِ CACHE_URL بهجای رسیدن به assertion، با
|
||||
# ImproperlyConfigured مربوط به CACHE_URL (نه SECRET_KEY) fail
|
||||
# میشد — یک false negative روی چیزی که این تست اصلاً قرار نیست
|
||||
# بسنجه. یک CACHE_URL معتبر هم ست میکنیم تا این تست فقط دقیقاً
|
||||
# همون چیزی که اسمش میگه (SECRET_KEY) رو بسنجه.
|
||||
settings_module = self._reload_settings_with_env(
|
||||
env_overrides={
|
||||
'DJANGO_DEBUG': '',
|
||||
'DJANGO_SECRET_KEY': 'prod-secret-xyz',
|
||||
'CACHE_URL': 'redis://localhost:6379/0',
|
||||
},
|
||||
)
|
||||
self.assertFalse(settings_module.DEBUG)
|
||||
self.assertEqual(settings_module.SECRET_KEY, 'prod-secret-xyz')
|
||||
|
||||
def test_debug_mode_missing_secret_key_uses_local_fallback(self):
|
||||
settings_module = self._reload_settings_with_env(
|
||||
env_overrides={'DJANGO_DEBUG': '1'},
|
||||
env_removed={'DJANGO_SECRET_KEY'},
|
||||
)
|
||||
self.assertTrue(settings_module.DEBUG)
|
||||
self.assertEqual(
|
||||
settings_module.SECRET_KEY,
|
||||
'django-insecure-jn!s*25lz^+bjm101tzmlz8jlj70i0qka++*h-(!0s^^vk-0ss',
|
||||
)
|
||||
|
||||
|
||||
class CacheUrlFailClosedTests(SimpleTestCase):
|
||||
"""
|
||||
🔒 تستِ متمرکز روی فیکسِ CACHE_URL: در پروداکشن (DEBUG=False)، اگه
|
||||
CACHE_URL ست نشده باشه، settings.py باید fail-closed بشه (خطای صریح
|
||||
موقعِ import)، نه fallback خاموش به LocMemCache (که بینِ worker/instance
|
||||
ها مشترک نیست و throttle/rate-limit ها رو بیاثر میکنه).
|
||||
"""
|
||||
|
||||
allow_database_queries = True
|
||||
|
||||
def _reload_settings_with_env(self, env_overrides, env_removed=()):
|
||||
from config import settings as settings_module
|
||||
|
||||
clean_env = {k: v for k, v in os.environ.items() if k not in env_removed}
|
||||
clean_env.update(env_overrides)
|
||||
with patch.dict(os.environ, clean_env, clear=True):
|
||||
importlib.reload(settings_module)
|
||||
return settings_module
|
||||
|
||||
def tearDown(self):
|
||||
from config import settings as settings_module
|
||||
importlib.reload(settings_module)
|
||||
|
||||
def test_production_missing_cache_url_fails_closed(self):
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
self._reload_settings_with_env(
|
||||
env_overrides={'DJANGO_DEBUG': '', 'DJANGO_SECRET_KEY': 'prod-secret-xyz'},
|
||||
env_removed={'CACHE_URL'},
|
||||
)
|
||||
|
||||
def test_debug_mode_missing_cache_url_uses_locmem_fallback(self):
|
||||
settings_module = self._reload_settings_with_env(
|
||||
env_overrides={'DJANGO_DEBUG': '1'},
|
||||
env_removed={'CACHE_URL'},
|
||||
)
|
||||
self.assertTrue(settings_module.DEBUG)
|
||||
self.assertEqual(
|
||||
settings_module.CACHES['default']['BACKEND'],
|
||||
'django.core.cache.backends.locmem.LocMemCache',
|
||||
)
|
||||
Reference in New Issue
Block a user