From 8c9836a20c35920c5a26e271cf9f9b18a4098c8a Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Thu, 23 Apr 2026 23:22:29 +0300 Subject: [PATCH] Add login-google, admin/errors routes and Google login methods --- app/Http/Controllers/AuthController.php | 132 ++++++++++++++++++++++++ app/Http/Controllers/MiscController.php | 20 ++++ routes/api.php | 5 + 3 files changed, 157 insertions(+) diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 006c4fc..d5dc7e1 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -592,6 +592,138 @@ class AuthController extends Controller ]); } + // ══════════════════════════════════════════════ + // GOOGLE LOGIN (Credential-based lookup) + // ══════════════════════════════════════════════ + + /** + * GET /v2/auth/passenger/login-google + * Replaces: auth/loginFromGooglePassenger.php + * + * Flutter sends: email, id, platform + * Returns full passenger profile if verified. + */ + public function passengerLoginGoogle(Request $request): JsonResponse + { + $request->validate([ + 'email' => 'required|string', + 'id' => 'required|string', + 'platform' => 'nullable|string', + ]); + + $email = $request->input('email'); + $id = $request->input('id'); + $platform = $request->input('platform', 'unknown'); + $appName = $request->input('appName', 'unknown'); + + // Encrypt email for DB lookup (V1 stores emails encrypted) + $encryptedEmail = $this->encryption->encrypt($email); + + // Complex query matching V1 exactly + $row = DB::connection('primary') + ->table('passengers as p') + ->leftJoin('phone_verification_passenger', 'phone_verification_passenger.phone_number', '=', 'p.phone') + ->leftJoin('invitesToPassengers', 'invitesToPassengers.inviterPassengerPhone', '=', 'p.phone') + ->leftJoin('promos', 'promos.passengerID', '=', 'p.id') + ->select([ + 'p.id', 'p.phone', 'p.email', 'p.gender', 'p.status', + 'p.birthdate', 'p.site', 'p.first_name', 'p.last_name', + 'p.sosPhone', 'p.education', 'p.employmentType', 'p.maritalStatus', + 'p.created_at', 'p.updated_at', + 'phone_verification_passenger.verified', + 'invitesToPassengers.isInstall', + 'invitesToPassengers.inviteCode', + 'invitesToPassengers.isGiftToken', + 'promos.promo_code as promo', + 'promos.amount as discount', + 'promos.validity_end_date as validity', + ]) + ->selectSub(function ($query) use ($platform, $appName) { + $query->from('packageInfo') + ->select('version') + ->where('platform', $platform) + ->where('appName', $appName) + ->limit(1); + }, 'package') + ->where('p.email', $encryptedEmail) + ->where('p.id', $id) + ->where('phone_verification_passenger.verified', '1') + ->first(); + + if (!$row) { + return response()->json([ + 'status' => 'Failure', + 'data' => 'User does not exist.', + ]); + } + + // Decrypt sensitive fields (matching V1 behavior) + $decryptedFields = [ + 'phone', 'email', 'gender', 'birthdate', 'site', + 'first_name', 'last_name', 'sosPhone', 'education', + 'employmentType', 'maritalStatus', + ]; + + $data = (array) $row; + foreach ($decryptedFields as $field) { + if (!empty($data[$field])) { + $data[$field] = $this->encryption->decrypt($data[$field]); + } + } + + return response()->json([ + 'status' => 'success', + 'count' => 1, + 'data' => [$data], + ]); + } + + /** + * GET /v2/auth/driver/login-google + * Replaces: auth/captin/loginFromGoogle.php + */ + public function driverLoginGoogle(Request $request): JsonResponse + { + $request->validate([ + 'email' => 'required|string', + 'id' => 'required|string', + ]); + + $encryptedEmail = $this->encryption->encrypt($request->input('email')); + + $driver = DB::connection('primary') + ->table('captain') + ->where('email', $encryptedEmail) + ->where('id', $request->input('id')) + ->first(); + + if (!$driver) { + return response()->json([ + 'status' => 'Failure', + 'data' => 'User does not exist.', + ]); + } + + $data = (array) $driver; + $decryptedFields = [ + 'phone', 'email', 'gender', 'birthdate', + 'first_name', 'last_name', 'national_number', + 'name_arabic', 'address', + ]; + + foreach ($decryptedFields as $field) { + if (!empty($data[$field])) { + $data[$field] = $this->encryption->decrypt($data[$field]); + } + } + + return response()->json([ + 'status' => 'success', + 'count' => 1, + 'data' => [$data], + ]); + } + // ══════════════════════════════════════════════ // HELPERS // ══════════════════════════════════════════════ diff --git a/app/Http/Controllers/MiscController.php b/app/Http/Controllers/MiscController.php index 77b794d..5a5c9f5 100644 --- a/app/Http/Controllers/MiscController.php +++ b/app/Http/Controllers/MiscController.php @@ -268,4 +268,24 @@ class MiscController extends Controller ]); } } + /** + * POST /v2/admin/errors + * Accepts client-side error reports from Flutter apps. + * Public endpoint (no auth required) — just logs the error. + */ + public function logClientError(Request $request): JsonResponse + { + $body = $request->getContent(); + + \Illuminate\Support\Facades\Log::channel('single')->warning('Client Error Report', [ + 'ip' => $request->ip(), + 'body' => substr($body, 0, 2000), // Limit to 2KB + 'user_agent' => $request->userAgent(), + ]); + + return response()->json([ + 'status' => 'success', + 'message' => 'Error logged', + ]); + } } diff --git a/routes/api.php b/routes/api.php index 6728206..c768ace 100644 --- a/routes/api.php +++ b/routes/api.php @@ -49,11 +49,13 @@ Route::prefix('v2/auth')->group(function () { Route::post('/passenger/login', [AuthController::class, 'passengerLogin']); Route::post('/passenger/register', [AuthController::class, 'passengerRegister']); Route::post('/passenger/wallet-login', [AuthController::class, 'passengerWalletLogin']); + Route::get('/passenger/login-google', [AuthController::class, 'passengerLoginGoogle']); // Driver Route::post('/driver/login', [AuthController::class, 'driverLogin']); Route::post('/driver/register', [AuthController::class, 'driverRegister']); Route::post('/driver/wallet-login', [AuthController::class, 'driverWalletLogin']); + Route::get('/driver/login-google', [AuthController::class, 'driverLoginGoogle']); // Admin & Service Route::post('/admin/login', [AuthController::class, 'adminLogin']); @@ -63,6 +65,9 @@ Route::prefix('v2/auth')->group(function () { Route::post('/driver/login-jwt', [AuthController::class, 'driverJwtHandshake']); }); +// Admin Error Logging (public — accepts error reports from Flutter apps) +Route::post('v2/admin/errors', [MiscController::class, 'logClientError']); + // Notification Tokens (Common for both) Route::post('v2/notifications/token', [NotificationController::class, 'updateToken']);