Implement critical security hardening and resolve a P0 bug in the discount code consumption flow. This update transitions the system from a development-heavy configuration to a production-ready state. Key changes: - Fix P0 bug where `consumeDiscountCode()` was missing, breaking order registration; replaced with a robust `DiscountCodeService` using `discount_code_usages` for audit trails and idempotency. - Implement strict production guards for the Zarinpal payment gateway to prevent accidental mock processing in live environments. - Refactor WordPress bridge asset management to use `filemtime` based versioning instead of `time()` to prevent unnecessary cache busting. - Remove debug-only hacks (`opcache_reset`, `header` cache control) from the WordPress plugin. - Enhance file upload security by enforcing strict `mimetypes` validation. - Update `.gitignore` to exclude sensitive WordPress configuration files and local PHPUnit caches. - Add comprehensive documentation for production deployment, including security checklists and key rotation procedures. - Update test suite to reflect new architecture and ensure 100% coverage of the discount service.
111 lines
5.7 KiB
Markdown
111 lines
5.7 KiB
Markdown
# 📦 بسته بروزرسانی IFNEX — فاز ۳.۸.۱ (سختسازی Production)
|
||
|
||
**تاریخ:** ۳۱ اکتبر ۲۰۲۶
|
||
**تعداد فایلها:** ۲۱ فایل + این راهنما
|
||
**⚠️ شامل یک فیکس بحرانی (P0):** باگ ثبت سفارش — حتماً اعمال شود
|
||
|
||
---
|
||
|
||
## 🚨 مهمترین فیکس: باگ P0 کد تخفیف
|
||
|
||
در بازبینی امنیتی کشف شد که متد `consumeDiscountCode()` در کنترلر سفارش **صدا زده میشد ولی هیچجا تعریف نشده بود** — یعنی:
|
||
|
||
> ❌ **ثبت سفارش مشتری در وضعیت فعلی کلاً خطای 500 میدهد!**
|
||
|
||
(این باگ از کامیت فلوی بازبینی/ارسال مجدد وارد کد شده بود و چون تستهای قدیمی شکسته بودند پنهان مانده بود)
|
||
|
||
**راهحل اعمالشده در این بسته:**
|
||
- سرویس جدید `DiscountCodeService` + جدول `discount_code_usages`
|
||
- مصرف یکبار هر کد + رکورد Audit کامل (چه کسی، چه سفارشی، چه مبلغی)
|
||
- قفل رقابتی (`lockForUpdate`) — دو ثبت همزمان نمیتوانند ظرفیت را دور بزنند
|
||
- خطای 422 با پیام واضح اگر کد بین محاسبه و ثبت منقضی شود
|
||
- گارد ظرفیت در قیمتگذاری هم
|
||
|
||
---
|
||
|
||
## 🔧 بقیه تغییرات (سختسازی Production)
|
||
|
||
| # | فیکس | توضیح |
|
||
|---|------|-------|
|
||
| ۱ | **گارد Mock Gateway** | اگر روی سرور `APP_ENV=production` باشد و درگاه تستی تنظیم شده باشد، پردازش با خطای صریح مسدود میشود (قبلاً خطر پرداخت مجازی واقعی وجود داشت!) |
|
||
| ۲ | **حذف هکهای دیباگ وردپرس** | `opcache_reset()` و `header('Cache-Control: no-store')` از ۵ فایل پلاگین حذف شد — در Production باعث header error و شکستن کش میشد |
|
||
| ۳ | **نسخهبندی سالم assetها** | cache-buster `'2.0.0-' . time()` (هر بار کش را میشکست) با `filemtime` جایگزین شد — کش فقط وقتی فایل عوض شود باطل میشود |
|
||
| ۴ | **سختسازی آپلود تعهدنامه** | `mimetypes` اضافه شد — محتوای واقعی فایل بررسی میشود نه فقط پسوند |
|
||
| ۵ | **`.env.example` بروز** | بلوک Production (لاگ روزانه، APP_DEBUG=false، کشها) + `IFNEX_BRIDGE_API_KEY` + راهنمای چرخش کلید |
|
||
| ۶ | **سند استقرار** | بخش جدید «۴.۴ چکلیست امنیتی سختسازی» در `DEPLOYMENT_HANDOFF.md` |
|
||
| ۷ | **تعمیر و توسعه تستها** | ۷ تست شکستهٔ قدیمی تعمیر شد + ۹ تست جدید → **۳۳ تست پاس، ۱۰۱ assertion** ✅ |
|
||
|
||
---
|
||
|
||
## ⚠️ دو فایل از گیت حذف شدهاند (اقدام دستی لازم!)
|
||
|
||
این بسته شامل حذف ۲ فایل از **ایندکس گیت** است (نه از دیسک!):
|
||
|
||
| فایل | دلیل |
|
||
|------|------|
|
||
| `03_WordPress/wp-config.php` | حاوی saltهای واقعی بود — لورفته فرض میشود؛ فقط `wp-config-sample.php` در مخزن میماند |
|
||
| `04_Laravel/.phpunit.result.cache` | فایل کش محلی — نباید در گیت باشد |
|
||
|
||
چون ZIP نمیتواند حذف انجام دهد، **بعد از اکسترکت** این دو دستور را در ریشه پروژه اجرا کنید:
|
||
|
||
```bash
|
||
git rm --cached 03_WordPress/wp-config.php
|
||
git rm --cached 04_Laravel/.phpunit.result.cache
|
||
```
|
||
|
||
> ✅ `.gitignore` بروز شده و بعد از این، این فایلها دیگر کامیت نمیشوند.
|
||
> فایل `wp-config.php` روی دیسک شما دستنخورده باقی میماند.
|
||
|
||
---
|
||
|
||
## 📥 روش نصب
|
||
|
||
1. محتوای پوشه `ifnex-updates/` را **دقیقاً روی ریشه پروژه IFNEX** اکسترکت کنید (Replace)
|
||
2. دو دستور `git rm --cached` بالا را اجرا کنید
|
||
3. مراحل بعد از اکسترکت (پایین) را انجام دهید
|
||
|
||
---
|
||
|
||
## ⚙️ مراحل بعد از اکسترکت
|
||
|
||
### Laravel:
|
||
```bash
|
||
cd 04_Laravel
|
||
|
||
# مایگریشن جدید (جدول discount_code_usages)
|
||
php artisan migrate
|
||
|
||
# اجرای تستها — باید ۳۳ پاس ببینید
|
||
php artisan test
|
||
```
|
||
|
||
### WordPress:
|
||
- پلاگین `ifnex-bridge` را غیرفعال و دوباره فعال کنید
|
||
- اگر کش افزونه دارید، پاکسازی کنید
|
||
|
||
---
|
||
|
||
## ✅ چکلیست تست سریع
|
||
|
||
| # | تست | نتیجه مورد انتظار |
|
||
|---|-----|-------------------|
|
||
| 1 | `php artisan test` | **33 passed, 101 assertions** |
|
||
| 2 | `php artisan migrate` | مایگریشن `discount_code_usages` بدون خطا |
|
||
| 3 | ثبت سفارش **بدون** کد تخفیف | موفق (این قبلاً 500 میداد!) |
|
||
| 4 | ثبت سفارش **با** کد تخفیف فعال | موفق + `used_count` کد +1 میشود |
|
||
| 5 | ثبت سفارش دوم با همان کد (اگر usage_limit=1) | خطای 422 با پیام واضح |
|
||
| 6 | فرم سفارش وردپرس | بدون خطای کنسول؛ assetها با `?ver=2.1.0.xxx` لود میشوند |
|
||
|
||
---
|
||
|
||
## 📤 بعد از تست موفق
|
||
|
||
```bash
|
||
git add -A
|
||
git commit -m "apply: IFNEX phase 3.8.1 package (production hardening + P0 discount fix)"
|
||
git push origin main
|
||
```
|
||
|
||
> ⚠️ **قبل از دیپلوی روی سرور:** چکلیست بخش ۴.۴ فایل `DEPLOYMENT_HANDOFF.md` را حتماً انجام دهید
|
||
> (چرخش کلیدها، بازتولید saltهای وردپرس، تنظیم درگاه واقعی، لاگ روزانه، کشها).
|