ifnex/04_Laravel/routes/api.php
Kazem Alghasi a5fd01dde1 chore(api): implement rate limiting for sensitive endpoints
Introduce granular rate limiting across various API categories to
improve security and prevent abuse. This includes protection against
brute-force attacks on authentication and SMS endpoints, as well as
resource management for public, customer, wallet, and staff APIs.

- Add `auth` rate limiter (5 requests/min per IP)
- Add `sms` rate limiter (1 request/min per phone/IP)
- Add `public` rate limiter (30 requests/min per IP)
- Add `customer` rate limiter (60 requests/min per user)
- Add `wallet` rate limiter (30 requests/min per user)
- Add `staff` rate limiter (60 requests/min per user)
- Apply middleware to corresponding routes in `api.php`
- Remove obsolete `test_pdf_generation.php` script
2026-10-04 01:35:22 +03:30

187 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use App\Http\Controllers\Api\CustomerFinancialController;
use App\Http\Controllers\Api\CommitmentFormController;
use App\Http\Controllers\Api\MobileVerificationController;
use App\Http\Controllers\Api\Customer\CustomerOrderController;
use App\Http\Controllers\Api\DiscountCodeController;
use App\Http\Controllers\Api\MockGatewayController;
use App\Http\Controllers\Api\PaymentController;
use App\Http\Controllers\Api\PricingController;
use App\Http\Controllers\Api\StaffOrderController;
use App\Http\Controllers\Api\TrackController;
use App\Http\Controllers\Api\WalletController;
use App\Http\Middleware\ApiKeyMiddleware;
use App\Http\Middleware\StaffApiMiddleware;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\BridgeAuthController;
use App\Http\Controllers\ShipmentPdfController;
// ══════════════════════════════════════════════════════════════
// Bridge Auth API (فقط برای پلاگین وردپرس - با API Key محافظت می‌شود)
// ══════════════════════════════════════════════════════════════
Route::post('/v1/bridge/login', [BridgeAuthController::class, 'login'])
->middleware('throttle:auth'); // Login — ۵/min per IP
// ══════════════════════════════════════════════════════════════
// API عمومی با API Key
// ══════════════════════════════════════════════════════════════
Route::middleware([ApiKeyMiddleware::class, 'throttle:public'])->prefix('v1')->group(function () {
Route::get('/track/{awb_no}', [TrackController::class, 'show']);
});
// ══════════════════════════════════════════════════════════════
// API عمومی (بدون نیاز به احراز هویت)
// ══════════════════════════════════════════════════════════════
Route::middleware(['throttle:public'])->prefix('v1')->group(function () {
Route::get('/countries', [CustomerOrderController::class, 'countries']);
});
// ══════════════════════════════════════════════════════════════
// Auth API (عمومی - برای دریافت توکن)
// ══════════════════════════════════════════════════════════════
Route::post('/v1/auth/login', [AuthController::class, 'login'])
->middleware('throttle:auth');
Route::middleware(['auth:sanctum'])->post('/v1/auth/logout', [AuthController::class, 'logout']);
// ══════════════════════════════════════════════════════════════
// API برای کاربران لاگین‌شده (با Sanctum / Bearer Token)
// ══════════════════════════════════════════════════════════════
Route::middleware(['auth:sanctum', 'throttle:customer'])->prefix('v1')->group(function () {
// ─── Wallet API (کاربر عادی) ───
Route::get('/wallet/balance', [WalletController::class, 'balance']);
Route::get('/wallet/transactions', [WalletController::class, 'transactions']);
// ─── Payment API ───
Route::post('/payment/redirect', [PaymentController::class, 'redirectToGateway'])
->middleware('throttle:wallet');
Route::get('/payment/check/{transaction}', [PaymentController::class, 'checkStatus'])
->middleware('throttle:wallet');
// ─── Admin Wallet API ───
Route::post('/wallet/admin-adjust', [WalletController::class, 'adminAdjust'])
->middleware('throttle:wallet');
Route::post('/wallet/{wallet}/freeze', [WalletController::class, 'freeze'])
->middleware('throttle:wallet');
Route::post('/wallet/{wallet}/unfreeze', [WalletController::class, 'unfreeze'])
->middleware('throttle:wallet');
Route::get('/wallet/{wallet}/activity-log', [WalletController::class, 'activityLog']);
// ─── Discount Codes (نیازمند احراز هویت) ───
Route::get('/discount-codes', [DiscountCodeController::class, 'index']);
Route::post('/discount-codes/validate', [DiscountCodeController::class, 'validate']);
// ─── Commitment Forms (نیازمند احراز هویت) ───
Route::get('/commitment-forms', [CommitmentFormController::class, 'index']);
Route::get('/commitment-forms/{direction}', [CommitmentFormController::class, 'byDirection']);
// ─── Customer Orders API (جدید) ───
Route::prefix('customer')->group(function () {
// پروفایل و آمار
Route::get('/profile', [CustomerOrderController::class, 'profile']);
// لیست کشورها (عمومی - بدون نیاز به احراز هویت)
// این endpoint در گروه auth:sanctum نیست
// سفارشات
Route::get('/orders', [CustomerOrderController::class, 'index']);
Route::post('/orders', [CustomerOrderController::class, 'store']);
Route::get('/orders/{shipment}', [CustomerOrderController::class, 'show']);
Route::post('/orders/{shipment}/cancel', [CustomerOrderController::class, 'cancel']);
Route::post('/orders/{shipment}/resubmit', [CustomerOrderController::class, 'resubmit']);
// دانلود PDFهای سفارش
Route::get('/orders/{shipment}/pdf/awb', [ShipmentPdfController::class, 'awb']);
Route::get('/orders/{shipment}/pdf/invoice', [ShipmentPdfController::class, 'invoice']);
Route::get('/orders/{shipment}/pdf/label', [ShipmentPdfController::class, 'label']);
Route::get('/orders/{shipment}/pdf/import-invoice', [ShipmentPdfController::class, 'importInvoice']);
// تعهدنامه‌ها
Route::get('/orders/{shipment}/commitment-forms', [CommitmentFormController::class, 'shipmentForms']);
Route::post('/orders/{shipment}/commitment-forms/{form}/upload', [CommitmentFormController::class, 'uploadSigned']);
Route::get('/orders/{shipment}/commitment-forms/{form}/download', [CommitmentFormController::class, 'downloadSigned'])
->name('customer.commitment-forms.download');
// دانلود قالب خام (محافظت‌شده با auth به جای symlink عمومی)
Route::get('/orders/{shipment}/commitment-forms/{form}/template', [CommitmentFormController::class, 'downloadTemplate'])
->name('customer.commitment-forms.template');
// نوتیفیکیشن‌ها
Route::get('/notifications', [CustomerOrderController::class, 'notifications']);
Route::post('/notifications/{notification}/read', [CustomerOrderController::class, 'markNotificationRead']);
// پرداخت سفارش
Route::post('/orders/{shipment}/pay-wallet', [CustomerOrderController::class, 'payFromWallet'])
->middleware('throttle:wallet');
Route::post('/orders/{shipment}/pay-gateway', [CustomerOrderController::class, 'payViaGateway'])
->middleware('throttle:wallet');
});
// ─── Staff Orders API (تأیید سفارشات) ───
Route::middleware([StaffApiMiddleware::class, 'throttle:staff'])
->prefix('staff')
->group(function () {
Route::get(
'/orders/pending-approval',
[StaffOrderController::class, 'pendingApproval']
);
Route::post(
'/orders/{shipment}/request-changes',
[StaffOrderController::class, 'requestChanges']
);
Route::post(
'/orders/{shipment}/approve',
[StaffOrderController::class, 'approve']
);
Route::post(
'/orders/{shipment}/reject',
[StaffOrderController::class, 'reject']
);
// ─── Customer Financial API ───
Route::get(
'/customers/search',
[CustomerFinancialController::class, 'search']
);
Route::get(
'/customers/{customer}/financial-status',
[CustomerFinancialController::class, 'financialStatus']
);
});
});
// ══════════════════════════════════════════════════════════════
// Mock Gateway Routes (عمومی - برای شبیه‌سازی درگاه)
// ══════════════════════════════════════════════════════════════
Route::prefix('v1/payment')->group(function () {
Route::get('/mock-gateway', [MockGatewayController::class, 'showGateway']);
Route::get('/mock-gateway/success', [MockGatewayController::class, 'simulateSuccess']);
Route::get('/mock-gateway/failure', [MockGatewayController::class, 'simulateFailure']);
});
// Callback از درگاه (بدون auth)
Route::any('/v1/payment/callback', [PaymentController::class, 'callback'])
->name('payment.callback')
->middleware('throttle:public');
// ══════════════════════════════════════════════════════════════
// APIهای عمومی (بدون auth) — فقط استعلام قیمت همگانی است
// ══════════════════════════════════════════════════════════════
Route::post('/v1/calculate', [PricingController::class, 'calculate'])
->middleware('throttle:public');
// API تأیید موبایل (عمومی)
Route::post('/v1/verify/send-code', [MobileVerificationController::class, 'sendCode'])
->middleware('throttle:sms'); // ۱/min per phone
Route::post('/v1/verify/check-code', [MobileVerificationController::class, 'checkCode'])
->middleware('throttle:auth'); // ۵/min per IP
// API ارسال پیامک (نیاز به auth دارد)
Route::middleware(['auth:sanctum'])->post('/v1/verify/send-sms', [MobileVerificationController::class, 'sendSms']);