diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index fa948f1..77773b3 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -579,6 +579,11 @@ class AuthController extends Controller return $this->failure('Invalid credentials'); } + // Verify password if set in DB, otherwise reject for security + if (!isset($admin->password) || !password_verify($request->input('password'), $admin->password)) { + return $this->failure('Invalid credentials'); + } + $jwt = $this->createJwt((string)$admin->id, 'admin', $request->input('device_number'), 900); return $this->success([ @@ -674,6 +679,8 @@ class AuthController extends Controller 'promos.promo_code as promo', 'promos.amount as discount', 'promos.validity_end_date as validity', + 'p.api_key', + 'p.api_secret', ]) ->selectSub(function ($query) use ($platform, $appName) { $query->from('packageInfo') @@ -732,6 +739,7 @@ class AuthController extends Controller ->table('captain') ->where('email', $encryptedEmail) ->where('id', $request->input('id')) + ->select('captain.*', 'captain.api_key', 'captain.api_secret') ->first(); if (!$driver) { @@ -795,6 +803,7 @@ class AuthController extends Controller 'iat' => time(), 'exp' => time() + $expiry, 'aud' => $audience, + 'iss' => 'Tripz', 'jti' => Str::uuid()->toString(), ]; @@ -826,25 +835,34 @@ class AuthController extends Controller ]); $audience = $request->input('aud'); - // Validate audience if needed (optional based on audio but good for security) - // if (!in_array($audience, config('intaleq.allowed_audiences'))) { ... } - - // The user mentioned using a fixed password like 'passenger' from Flutter - // and relying on fingerprint for security. - // Generate a 24h JWT for the handshake (as requested to be consistent) + // Verify the passenger exists + $passenger = Passenger::where('id', $request->input('id'))->first(); + if (!$passenger) { + return $this->failure('Invalid credentials'); + } + + // Verify fingerprint matches stored device (security) + $token = PassengerToken::where('passengerID', $request->input('id'))->first(); + if (!$token || !hash_equals($token->fingerPrint ?? '', $request->input('fingerPrint'))) { + return $this->failure('Device verification failed', 403); + } + + // Generate a 15min JWT for the handshake (security: reduced from 24h) $jwt = $this->createJwt( $request->input('id'), 'passenger', $request->input('fingerPrint'), - 86400, + 900, $audience ); return response()->json([ 'status' => 'success', 'jwt' => $jwt, - 'expires_in' => 86400 + 'expires_in' => 900, + 'api_key' => $passenger->api_key ?? $driver->api_key, + 'api_secret' => $passenger->api_secret ?? $driver->api_secret, ]); } @@ -861,18 +879,30 @@ class AuthController extends Controller 'aud' => 'required|string', ]); + $driver = Driver::where('id', $request->input('id'))->first(); + if (!$driver) { + return $this->failure('Invalid credentials'); + } + + $token = DriverToken::where('captain_id', $request->input('id'))->first(); + if (!$token || !hash_equals($token->fingerPrint ?? '', $request->input('fingerPrint'))) { + return $this->failure('Device verification failed', 403); + } + $jwt = $this->createJwt( $request->input('id'), 'driver', $request->input('fingerPrint'), - 86400, + 900, $request->input('aud') ); return response()->json([ 'status' => 'success', 'jwt' => $jwt, - 'expires_in' => 86400 + 'expires_in' => 900, + 'api_key' => $passenger->api_key ?? $driver->api_key, + 'api_secret' => $passenger->api_secret ?? $driver->api_secret, ]); } diff --git a/app/Http/Controllers/DriverDocController.php b/app/Http/Controllers/DriverDocController.php index cdb0c3e..c8c1a61 100644 --- a/app/Http/Controllers/DriverDocController.php +++ b/app/Http/Controllers/DriverDocController.php @@ -11,14 +11,14 @@ class DriverDocController extends Controller /** POST /v2/driver/scams */ public function reportScam(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); + $userId = $request->attributes->get('_jwt_user_id'); return response()->json(['status' => 'success']); } /** GET /v2/driver/registration-car */ public function getCarReg(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); + $userId = $request->attributes->get('_jwt_user_id'); $data = DB::connection('primary')->table('RegisrationCar') ->where('driverID', $userId)->get(); return response()->json(['status' => 'success', 'data' => $data]); @@ -27,7 +27,7 @@ class DriverDocController extends Controller /** POST /v2/driver/registration-car */ public function storeCarReg(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); + $userId = $request->attributes->get('_jwt_user_id'); // Logic to store... return response()->json(['status' => 'success']); } diff --git a/app/Http/Controllers/InviteController.php b/app/Http/Controllers/InviteController.php index b220839..8b36cf5 100644 --- a/app/Http/Controllers/InviteController.php +++ b/app/Http/Controllers/InviteController.php @@ -105,7 +105,7 @@ class InviteController extends Controller /** GET /v2/invites/gift */ public function checkGift(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); + $userId = $request->attributes->get('_jwt_user_id'); return response()->json([ 'status' => 'success', 'message' => ['gift_available' => true] diff --git a/app/Http/Controllers/MiscController.php b/app/Http/Controllers/MiscController.php index 5a5c9f5..c37d314 100644 --- a/app/Http/Controllers/MiscController.php +++ b/app/Http/Controllers/MiscController.php @@ -185,7 +185,8 @@ class MiscController extends Controller return response()->json(['status' => 'success', 'message' => 'Help question saved successfully']); } catch (\Exception $e) { - return response()->json(['status' => 'failure', 'message' => 'Database error: ' . $e->getMessage()]); + \Log::error('MiscController HelpCenter Error: ' . $e->getMessage()); + return response()->json(['status' => 'failure', 'message' => 'An error occurred']); } } @@ -212,7 +213,8 @@ class MiscController extends Controller return response()->json(['status' => 'success', 'message' => 'Tip inserted successfully']); } catch (\Exception $e) { - return response()->json(['status' => 'failure', 'message' => 'Database error: ' . $e->getMessage()]); + \Log::error('MiscController Tips Error: ' . $e->getMessage()); + return response()->json(['status' => 'failure', 'message' => 'An error occurred']); } } @@ -262,9 +264,10 @@ class MiscController extends Controller ]); } } catch (\Exception $e) { + \Log::error('MiscController EgyptPhones Error: ' . $e->getMessage()); return response()->json([ 'status' => 'failure', - 'message' => 'Database error: ' . $e->getMessage() + 'message' => 'An error occurred' ]); } } diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php index 21aa2c7..3772fee 100644 --- a/app/Http/Controllers/NotificationController.php +++ b/app/Http/Controllers/NotificationController.php @@ -21,8 +21,8 @@ class NotificationController extends Controller /** GET /v2/notifications */ public function index(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); - $userType = $request->input('_jwt_user_type'); + $userId = $request->attributes->get('_jwt_user_id'); + $userType = $request->attributes->get('_jwt_user_type'); $page = (int) $request->input('page', 1); $limit = min((int) $request->input('limit', 20), 50); @@ -46,7 +46,7 @@ class NotificationController extends Controller /** PUT /v2/notifications/{id}/read */ public function markRead(Request $request, int $id): JsonResponse { - $userType = $request->input('_jwt_user_type'); + $userType = $request->attributes->get('_jwt_user_type'); $table = $userType === 'driver' ? 'notificationCaptain' : 'notifications'; DB::connection('primary')->table($table) @@ -63,8 +63,8 @@ class NotificationController extends Controller 'fingerPrint' => 'required|string', ]); - $userId = $request->input('_jwt_user_id') ?? $request->input('passengerID'); - $userType = $request->input('_jwt_user_type') ?? 'passenger'; + $userId = $request->attributes->get('_jwt_user_id') ?? $request->input('passengerID'); + $userType = $request->attributes->get('_jwt_user_type') ?? 'passenger'; if (!$userId) { return response()->json(['status' => 'failure', 'message' => 'User ID missing'], 400); @@ -98,8 +98,8 @@ class NotificationController extends Controller /** GET /v2/notifications/token */ public function getToken(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id') ?? $request->input('passengerID'); - $userType = $request->input('_jwt_user_type') ?? 'passenger'; + $userId = $request->attributes->get('_jwt_user_id') ?? $request->input('passengerID'); + $userType = $request->attributes->get('_jwt_user_type') ?? 'passenger'; if (!$userId) { return response()->json(['status' => 'failure', 'message' => 'User ID missing'], 400); diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 142192f..47518fa 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -35,7 +35,7 @@ class ProfileController extends Controller */ public function passenger(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $passenger = Passenger::active()->find($id); if (!$passenger) { @@ -64,7 +64,7 @@ class ProfileController extends Controller */ public function driver(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $driver = Driver::active()->byId($id)->first(); if (!$driver) { @@ -101,7 +101,7 @@ class ProfileController extends Controller */ public function updatePassenger(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $passenger = Passenger::active()->find($id); if (!$passenger) { @@ -135,7 +135,7 @@ class ProfileController extends Controller { $request->validate(['email' => 'required|email']); - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $driver = Driver::active()->byId($id)->first(); if (!$driver) { diff --git a/app/Http/Controllers/PromoController.php b/app/Http/Controllers/PromoController.php index 9426fad..68ec261 100644 --- a/app/Http/Controllers/PromoController.php +++ b/app/Http/Controllers/PromoController.php @@ -21,7 +21,7 @@ class PromoController extends Controller /** GET /v2/promos */ public function index(Request $request): JsonResponse { - $passengerId = $request->input('_jwt_user_id'); + $passengerId = $request->attributes->get('_jwt_user_id'); $promos = DB::connection('primary')->table('promos') ->where('passengerID', $passengerId) @@ -70,7 +70,7 @@ class PromoController extends Controller 'amount' => 'required|string', ]); - $passengerId = $request->input('_jwt_user_id'); + $passengerId = $request->attributes->get('_jwt_user_id'); $exists = DB::connection('primary')->table('promos') ->where('passengerID', $passengerId)->exists(); diff --git a/app/Http/Controllers/RatingController.php b/app/Http/Controllers/RatingController.php index 7b8a318..7feab1e 100644 --- a/app/Http/Controllers/RatingController.php +++ b/app/Http/Controllers/RatingController.php @@ -29,7 +29,7 @@ class RatingController extends Controller 'comment' => 'nullable|string|max:500', ]); - $passengerId = $request->input('_jwt_user_id'); + $passengerId = $request->attributes->get('_jwt_user_id'); // Prevent duplicate ratings $exists = DB::connection('primary')->table('ratingDriver') @@ -60,7 +60,7 @@ class RatingController extends Controller 'comment' => 'nullable|string|max:500', ]); - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); $exists = DB::connection('primary')->table('ratingPassenger') ->where('rideId', $request->input('ride_id'))->exists(); @@ -88,8 +88,8 @@ class RatingController extends Controller 'comment' => 'nullable|string|max:300', ]); - $userId = $request->input('_jwt_user_id'); - $userType = $request->input('_jwt_user_type'); + $userId = $request->attributes->get('_jwt_user_id'); + $userType = $request->attributes->get('_jwt_user_type'); DB::connection('primary')->table('ratingApp')->insert([ 'name' => $request->input('name', ''), diff --git a/app/Http/Controllers/RideController.php b/app/Http/Controllers/RideController.php index 722dc6d..842e499 100644 --- a/app/Http/Controllers/RideController.php +++ b/app/Http/Controllers/RideController.php @@ -66,7 +66,7 @@ class RideController extends Controller 'passenger_rating' => 'nullable|numeric', ]); - $passengerId = $request->input('_jwt_user_id'); + $passengerId = $request->attributes->get('_jwt_user_id'); // Prevent duplicate active rides $activeRide = DB::connection('ride')->table('ride') @@ -152,7 +152,7 @@ class RideController extends Controller */ public function accept(Request $request, int $rideId): JsonResponse { - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); DB::connection('ride')->beginTransaction(); try { @@ -233,7 +233,7 @@ class RideController extends Controller */ public function start(Request $request, int $rideId): JsonResponse { - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); $ride = Ride::where('id', $rideId) ->where('driver_id', $driverId) @@ -280,7 +280,7 @@ class RideController extends Controller */ public function arrive(Request $request, int $rideId): JsonResponse { - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); $ride = Ride::where('id', $rideId) ->where('driver_id', $driverId) @@ -316,7 +316,7 @@ class RideController extends Controller */ public function finish(Request $request, int $rideId): JsonResponse { - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); $request->validate([ 'price_for_driver' => 'required|numeric', @@ -397,7 +397,7 @@ class RideController extends Controller */ public function cancelByPassenger(Request $request, int $rideId): JsonResponse { - $passengerId = $request->input('_jwt_user_id'); + $passengerId = $request->attributes->get('_jwt_user_id'); $ride = Ride::where('id', $rideId) ->where('passenger_id', $passengerId) @@ -452,7 +452,7 @@ class RideController extends Controller */ public function cancelByDriver(Request $request, int $rideId): JsonResponse { - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); $ride = Ride::where('id', $rideId) ->where('driver_id', $driverId) @@ -520,8 +520,8 @@ class RideController extends Controller */ public function active(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); - $userType = $request->input('_jwt_user_type'); + $userId = $request->attributes->get('_jwt_user_id'); + $userType = $request->attributes->get('_jwt_user_type'); $query = Ride::active(); if ($userType === 'driver') { @@ -544,8 +544,8 @@ class RideController extends Controller */ public function index(Request $request): JsonResponse { - $userId = $request->input('_jwt_user_id'); - $userType = $request->input('_jwt_user_type'); + $userId = $request->attributes->get('_jwt_user_id'); + $userType = $request->attributes->get('_jwt_user_type'); $page = $request->input('page', 1); $limit = min($request->input('limit', 20), 50); diff --git a/app/Http/Controllers/TrackingController.php b/app/Http/Controllers/TrackingController.php index 3cde23c..7c8b8ca 100644 --- a/app/Http/Controllers/TrackingController.php +++ b/app/Http/Controllers/TrackingController.php @@ -196,7 +196,7 @@ class TrackingController extends Controller /** GET /v2/tracking/captain-stats */ public function captainStats(Request $request): JsonResponse { - $driverId = $request->input('_jwt_user_id'); + $driverId = $request->attributes->get('_jwt_user_id'); $totalRides = DB::connection('ride')->table('ride') ->where('driver_id', $driverId) diff --git a/app/Http/Controllers/UploadController.php b/app/Http/Controllers/UploadController.php index 68568ac..87dec57 100644 --- a/app/Http/Controllers/UploadController.php +++ b/app/Http/Controllers/UploadController.php @@ -86,7 +86,7 @@ class UploadController extends Controller return response()->json(['status' => 'failure', 'message' => 'File too large'], 400); } - $userId = $request->input('_jwt_user_id'); + $userId = $request->attributes->get('_jwt_user_id'); $ext = $file->getClientOriginalExtension() ?: 'mp3'; $filename = 'audio_' . Str::random(24) . '.' . $ext; @@ -130,7 +130,7 @@ class UploadController extends Controller } // Generate safe filename - $userId = $request->input('_jwt_user_id'); + $userId = $request->attributes->get('_jwt_user_id'); $ext = match ($mime) { 'image/jpeg' => 'jpg', 'image/png' => 'png', diff --git a/app/Http/Controllers/WalletController.php b/app/Http/Controllers/WalletController.php index 592ae55..fbb2f44 100644 --- a/app/Http/Controllers/WalletController.php +++ b/app/Http/Controllers/WalletController.php @@ -25,7 +25,7 @@ class WalletController extends Controller /** GET /v2/wallet/passenger */ public function index(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $wallet = DB::connection('primary')->table('passengerWallet') ->where('passenger_id', $id)->first(); @@ -38,7 +38,7 @@ class WalletController extends Controller /** GET /v2/wallet/passenger/balance */ public function balance(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $bal = DB::connection('primary')->table('passengerWallet') ->where('passenger_id', $id)->value('balance') ?? '0.00'; @@ -53,7 +53,7 @@ class WalletController extends Controller 'payment_method' => 'required|string', ]); - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); DB::connection('primary')->beginTransaction(); try { @@ -95,15 +95,22 @@ class WalletController extends Controller } } - /** PUT /v2/wallet/passenger */ + /** PUT /v2/wallet/passenger — ADMIN ONLY */ public function update(Request $request): JsonResponse { - $request->validate(['balance' => 'required|numeric|min:0']); + // Only admins can directly set balance + $userType = $request->attributes->get('_jwt_user_type'); + if ($userType !== 'admin') { + return response()->json(['status' => 'failure', 'message' => 'Unauthorized'], 403); + } - $id = $request->input('_jwt_user_id'); + $request->validate([ + 'balance' => 'required|numeric|min:0', + 'passenger_id' => 'required|string', + ]); DB::connection('primary')->table('passengerWallet') - ->where('passenger_id', $id) + ->where('passenger_id', $request->input('passenger_id')) ->update(['balance' => $request->input('balance')]); return response()->json(['status' => 'success']); @@ -112,7 +119,7 @@ class WalletController extends Controller /** DELETE /v2/wallet/passenger */ public function destroy(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); DB::connection('primary')->table('passengerWallet') ->where('passenger_id', $id)->delete(); @@ -122,7 +129,7 @@ class WalletController extends Controller /** GET /v2/wallet/passenger/transactions */ public function transactions(Request $request): JsonResponse { - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); $page = (int) $request->input('page', 1); $limit = min((int) $request->input('limit', 20), 50); @@ -145,7 +152,7 @@ class WalletController extends Controller 'amount' => 'required|numeric|min:0.01', ]); - $id = $request->input('_jwt_user_id'); + $id = $request->attributes->get('_jwt_user_id'); DB::connection('primary')->table('payment_tokens_passenger')->insert([ 'token' => $request->input('token'), diff --git a/app/Http/Middleware/AdminMiddleware.php b/app/Http/Middleware/AdminMiddleware.php index 14f1d8b..e2ff287 100644 --- a/app/Http/Middleware/AdminMiddleware.php +++ b/app/Http/Middleware/AdminMiddleware.php @@ -20,7 +20,7 @@ class AdminMiddleware { public function handle(Request $request, Closure $next) { - $userType = $request->input('_jwt_user_type'); + $userType = $request->attributes->get('_jwt_user_type'); if ($userType !== 'admin') { return response()->json([ diff --git a/app/Http/Middleware/HmacAuthMiddleware.php b/app/Http/Middleware/HmacAuthMiddleware.php index 7275dbc..8a69bb4 100644 --- a/app/Http/Middleware/HmacAuthMiddleware.php +++ b/app/Http/Middleware/HmacAuthMiddleware.php @@ -33,10 +33,69 @@ class HmacAuthMiddleware public function handle(Request $request, Closure $next) { - // In V2 transition, we allow requests without HMAC to pass through - // as long as they have a valid JWT (checked by next middleware). - // This maintains compatibility while we update the database schema. + $signature = $request->header('X-Signature'); + $timestamp = $request->header('X-Timestamp'); + $nonce = $request->header('X-Nonce'); + $apiKey = $request->header('X-API-Key'); + + // All headers required + if (!$signature || !$timestamp || !$nonce || !$apiKey) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Missing security headers' + ], 401); + } + + // Reject if timestamp older than tolerance (replay protection) + $tolerance = config('intaleq.hmac_tolerance', 300); + if (abs(time() - (int) $timestamp) > $tolerance) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Request expired' + ], 401); + } + + // Nonce replay check (prevent duplicate requests) + $nonceKey = 'nonce:' . $nonce; + if (Cache::has($nonceKey)) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Duplicate request' + ], 401); + } + Cache::put($nonceKey, true, $tolerance); + + // Lookup api_secret by api_key + $user = DB::connection('primary')->table('passengers') + ->where('api_key', $apiKey)->first(['api_secret']); + if (!$user) { + $user = DB::connection('primary')->table('driver') + ->where('api_key', $apiKey)->first(['api_secret']); + } + if (!$user) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Invalid API key' + ], 401); + } + + // Compute expected signature + // METHOD:PATH:TIMESTAMP:NONCE:BODY + $method = strtoupper($request->method()); + $path = $request->path(); // returns path without leading slash (e.g. v2/ride/create) + $body = $request->getContent(); + + $payload = "$method:$path:$timestamp:$nonce:$body"; + $expected = hash_hmac(self::ALGORITHM, $payload, $user->api_secret); + + if (!hash_equals($expected, $signature)) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Invalid signature' + ], 401); + } + return $next($request); } } diff --git a/app/Http/Middleware/JwtAuthMiddleware.php b/app/Http/Middleware/JwtAuthMiddleware.php index 751e044..69e662a 100644 --- a/app/Http/Middleware/JwtAuthMiddleware.php +++ b/app/Http/Middleware/JwtAuthMiddleware.php @@ -38,12 +38,19 @@ class JwtAuthMiddleware try { $decoded = JWT::decode($token, new Key(config('intaleq.jwt_secret'), 'HS256')); - // Attach JWT claims to request - $request->merge([ - '_jwt_user_id' => $decoded->user_id ?? null, - '_jwt_user_type' => $decoded->user_type ?? null, - '_jwt_fingerprint' => $decoded->fingerprint ?? null, - ]); + // Verify issuer (defense in depth) + $iss = $decoded->iss ?? ''; + if (!in_array($iss, ['Tripz', 'Tripz-Wallet'])) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Invalid token issuer' + ], 401); + } + + // Attach JWT claims to request attributes (internal, not spoofable via POST/GET) + $request->attributes->set('_jwt_user_id', $decoded->user_id ?? null); + $request->attributes->set('_jwt_user_type', $decoded->user_type ?? null); + $request->attributes->set('_jwt_fingerprint', $decoded->fingerprint ?? null); return $next($request); diff --git a/bootstrap/app.php b/bootstrap/app.php index eb9b577..cf7c58c 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -20,16 +20,30 @@ return Application::configure(basePath: dirname(__DIR__)) // Global API middleware $middleware->api(prepend: [ \Illuminate\Http\Middleware\HandleCors::class, + 'throttle:120,1', ]); }) ->withExceptions(function (Exceptions $exceptions) { - // سنظهر الخطأ الحقيقي لنعرف ماذا يحدث في الـ login-jwt $exceptions->render(function (\Throwable $e) { + \Log::error('Unhandled Exception', [ + 'message' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'trace' => $e->getTraceAsString(), + ]); + + if (config('app.debug')) { + return response()->json([ + 'status' => 'failure', + 'message' => 'DEBUG ERROR: ' . $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine() + ], 500); + } + return response()->json([ 'status' => 'failure', - 'message' => 'DEBUG ERROR: ' . $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine() + 'message' => 'Internal server error', ], 500); }); }) diff --git a/config/database.php b/config/database.php index c6099b2..83a9b36 100644 --- a/config/database.php +++ b/config/database.php @@ -30,12 +30,12 @@ return [ 'port' => env('DB_PRIMARY_PORT', '3306'), 'database' => env('DB_PRIMARY_NAME_V2', 'intaleqDBV2'), 'username' => env('DB_PRIMARY_USER_V2', 'intaleqUserV2'), - 'password' => env('DB_PRIMARY_PASS_V2', 'cqdEGlg'), + 'password' => env('DB_PRIMARY_PASS_V2', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_general_ci', 'prefix' => '', - 'strict' => false, + 'strict' => true, 'engine' => 'InnoDB', 'timezone' => '+03:00', 'options' => extension_loaded('pdo_mysql') ? [ @@ -61,7 +61,7 @@ return [ 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_general_ci', 'prefix' => '', - 'strict' => false, + 'strict' => true, 'engine' => 'InnoDB', 'timezone' => '+03:00', 'options' => extension_loaded('pdo_mysql') ? [ @@ -86,7 +86,7 @@ return [ 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_general_ci', 'prefix' => '', - 'strict' => false, + 'strict' => true, 'engine' => 'InnoDB', 'timezone' => '+03:00', 'options' => extension_loaded('pdo_mysql') ? [ diff --git a/config/intaleq.php b/config/intaleq.php index 58dcefa..4f90894 100644 --- a/config/intaleq.php +++ b/config/intaleq.php @@ -45,9 +45,9 @@ return [ // 'internal_socket_key_path' => env('INTERNAL_SOCKET_KEY_PATH', base_path('.internal_socket_key')), // Rate Limiting - 'rate_limit_login' => (int) env('RATE_LIMIT_LOGIN', 5), + 'rate_limit_login' => (int) env('RATE_LIMIT_LOGIN', 3), 'rate_limit_login_decay' => (int) env('RATE_LIMIT_LOGIN_DECAY', 60), - 'rate_limit_api' => (int) env('RATE_LIMIT_API', 60), + 'rate_limit_api' => (int) env('RATE_LIMIT_API', 120), 'rate_limit_api_decay' => (int) env('RATE_LIMIT_API_DECAY', 60), // Upload