stop a deploy from silently blocking the frontend or leaving 0000 open
سه حالتِ خراب که هیچکدام در لاگِ سرور ردی نمیگذارند و فقط وقتی کشف میشدند که یک آدم از بیرون اپ را دستی امتحان کند. CORS_ALLOWED_ORIGINS فقط از env خوانده میشد و با DEBUG روشن به localhost محدود میماند. یعنی بکاندِ کاملاً سالم، ولی مرورگر همهی درخواستهای math.tadrisino2.ir را بلاک میکند — خطایی که سمتِ سرور دیده نمیشود و فقط در کنسولِ مرورگر پیداست. origin های شناختهشده حالا پیشفرضِ داخلِ کدند تا یک متغیرِ فراموششده اتصال را نشکند؛ env همچنان بازنویسیشان میکند. /api/health حالا warnings هم میدهد. مهمترینش: با DEBUG روشن روی سرورِ عمومی، DEV_MASTER_OTP یعنی هر کسی با کدِ 0000 میتواند بهجای هر شمارهای وارد شود. این تا امروز فقط با خواندنِ تنظیماتِ سرور معلوم میشد، و ما به سرور دسترسی نداریم. allowedOrigins هم برگردانده میشود تا مشکلِ CORS از بیرون قابلِ تشخیص باشد. deploy.sh قبل از دست زدن به دیتابیس متغیرهای لازم را بررسی میکند و با پیامِ روشن میایستد، بهجای اینکه وسطِ کار بشکند و 502 بدهد. .env.production.example همانها را یکجا مستند میکند. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,30 @@ def _check_integrations() -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _warnings() -> list[str]:
|
||||
"""
|
||||
چیزهایی که خرابی نیستند ولی روی یک سرورِ عمومی خطرناکاند.
|
||||
|
||||
اینجا هستند چون تنها راهِ دیدنشان تا امروز این بود که کسی تنظیماتِ سرور را
|
||||
از نزدیک بخواند — و ما به سرور دسترسی نداریم.
|
||||
"""
|
||||
out = []
|
||||
if settings.DEBUG:
|
||||
out.append(
|
||||
'DEBUG روشن است: صفحههای خطا کلِ تنظیمات و traceback را نشان میدهند، '
|
||||
'و کدِ ورودِ آزمایشیِ 0000 برای هر شمارهای پذیرفته میشود. '
|
||||
'روی سرورِ عمومی باید خاموش باشد.'
|
||||
)
|
||||
if getattr(settings, 'DEV_MASTER_OTP', None) is not None:
|
||||
out.append('کدِ یکسانِ ورود (DEV_MASTER_OTP) فعال است — هر کسی میتواند بهجای هر کاربری وارد شود.')
|
||||
backend = settings.CACHES['default']['BACKEND']
|
||||
if not settings.DEBUG and 'LocMem' in backend:
|
||||
out.append('کش محلیِ هر پروسه است؛ محدودیتِ نرخ بینِ workerها مشترک نیست.')
|
||||
if not getattr(settings, 'CORS_ALLOWED_ORIGINS', None):
|
||||
out.append('هیچ origin ای برای CORS مجاز نیست — مرورگر همهی درخواستهای فرانت را بلاک میکند.')
|
||||
return out
|
||||
|
||||
|
||||
class HealthView(APIView):
|
||||
"""
|
||||
GET /api/health — وضعیتِ این نسخهی مستقرشده.
|
||||
@@ -110,10 +134,13 @@ class HealthView(APIView):
|
||||
}
|
||||
critical_ok = all(checks[k]['ok'] for k in ('database', 'migrations', 'cache'))
|
||||
|
||||
warnings = _warnings()
|
||||
payload = {
|
||||
'status': 'ok' if critical_ok else 'error',
|
||||
'debug': bool(settings.DEBUG),
|
||||
'warnings': warnings,
|
||||
'checks': checks,
|
||||
'integrations': _check_integrations(),
|
||||
'allowedOrigins': list(getattr(settings, 'CORS_ALLOWED_ORIGINS', [])),
|
||||
}
|
||||
return Response(payload, status=200 if critical_ok else 503)
|
||||
|
||||
@@ -61,15 +61,18 @@ CSRF_TRUSTED_ORIGINS = [o for o in os.environ.get('CSRF_TRUSTED_ORIGINS', '').sp
|
||||
# هدر است، پس origin ناشناس نباید بتواند از مرورگرِ کاربر به API ما بزند.
|
||||
# CORS_ALLOW_CREDENTIALS هم عمداً خاموش میماند — کوکیای در کار نیست و روشن
|
||||
# کردنش فقط سطحِ حمله اضافه میکند.
|
||||
# origin های شناختهشدهی فرانت. عمداً اینجا و نه فقط در متغیرِ محیطی: اگر
|
||||
# تنها راهش env بود، یک دیپلویِ فراموششده یعنی بکاندِ سالم که مرورگر همهی
|
||||
# درخواستهایش را بلاک میکند — خطایی که در سمتِ سرور هیچ ردی نمیگذارد و فقط
|
||||
# در کنسولِ مرورگر دیده میشود.
|
||||
CORS_DEFAULT_ORIGINS = [
|
||||
'https://math.tadrisino2.ir', # فرانتِ مستقر
|
||||
'http://localhost:3000', 'http://127.0.0.1:3000',
|
||||
'http://localhost:5173', 'http://127.0.0.1:5173', # Vite/CRA محلی
|
||||
]
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
o for o in os.environ.get('CORS_ALLOWED_ORIGINS', '').split(',') if o
|
||||
]
|
||||
if DEBUG and not CORS_ALLOWED_ORIGINS:
|
||||
# پورتهای پیشفرضِ Vite/CRA برای توسعهی محلی.
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
'http://localhost:3000', 'http://127.0.0.1:3000',
|
||||
'http://localhost:5173', 'http://127.0.0.1:5173',
|
||||
]
|
||||
] or CORS_DEFAULT_ORIGINS
|
||||
CORS_ALLOW_CREDENTIALS = False
|
||||
# فقط مسیرهای API؛ /admin/ و فایلهای استاتیک لازم نیست از origin دیگر خوانده شوند.
|
||||
CORS_URLS_REGEX = r'^/api/.*$'
|
||||
|
||||
Reference in New Issue
Block a user