validate([ 'machine' => 'required|string', 'Su_Account' => 'required|string', 'Su_Password' => 'required|string', 'ip' => 'nullable|string', 'type' => 'nullable|string', ]); // 2. 透過帳號尋找使用者 (允許使用 username 或 email) $user = User::where('username', $validated['Su_Account']) ->orWhere('email', $validated['Su_Account']) ->first(); // 若無此帳號或密碼錯誤 if (!$user || !Hash::check($validated['Su_Password'], $user->password)) { Log::warning("B000 機台登入失敗: 帳密錯誤", [ 'account' => $validated['Su_Account'], 'machine' => $validated['machine'] ]); // 按現行設定,Java 端只認 Success 字串,其餘視為帳密錯誤 return response()->json(['message' => 'Failed']); } // 3. 取得機台物件 // 因為此 API 無狀態 (沒有登入 session),為了避免被 global scope 擋住,直接取消所有 scope 來撈取 $machine = Machine::withoutGlobalScopes()->where('serial_no', $validated['machine'])->first(); if (!$machine) { Log::warning("B000 機台登入失敗: 伺服器找不到該機台", [ 'machine_serial' => $validated['machine'] ]); return response()->json(['message' => 'Failed']); } // 4. RBAC 權限驗證 (遵循多租戶與機台授權規範) if ($user->isSystemAdmin()) { // [系統管理員] : 擁有最高權限,可登入平台下轄所有機台,直接放行 } elseif ($user->is_admin) { // [公司管理員] : 不需要檢查 machine_user 表,但【必須驗證】該機台是否隸屬於他的公司 if ($machine->company_id !== $user->company_id) { Log::warning("B000 機台登入失敗: 企圖越權登入其他公司的機台", [ 'user_id' => $user->id, 'user_company' => $user->company_id, 'machine_company' => $machine->company_id ]); return response()->json(['message' => 'Forbidden']); } } else { // [一般租戶帳號] : (包括補貨員等)必須嚴格檢查該帳號有沒有被分配到這台機器的 machine_user 關聯授權 if (!$user->machines()->where('machine_id', $machine->id)->exists()) { Log::warning("B000 機台登入失敗: 該帳號沒有此機台的授權", [ 'user_id' => $user->id, 'machine_id' => $machine->id ]); return response()->json(['message' => 'Forbidden']); } } // 5. 驗證完美通過!回傳固定字串 Success 讓 Java 端放行 Log::info("B000 機台登入成功", [ 'account' => $user->username, 'machine' => $machine->serial_no ]); return response()->json([ 'message' => 'Success' ]); } }