From 38f50719756488fbd1986513e8888c73c5b8a3c8 Mon Sep 17 00:00:00 2001 From: sky121113 Date: Wed, 24 Jun 2026 15:39:41 +0800 Subject: [PATCH] =?UTF-8?q?[FIX]=20=E5=8F=96=E8=B2=A8=E7=A2=BC/=E9=80=9A?= =?UTF-8?q?=E8=A1=8C=E7=A2=BC/=E4=BE=86=E5=BA=97=E7=A6=AE=EF=BC=9A?= =?UTF-8?q?=E5=AE=A2=E6=88=B6=E5=B8=B3=E8=99=9F=E8=B7=A8=E6=9C=AA=E6=8E=88?= =?UTF-8?q?=E6=AC=8A=E6=A9=9F=E5=8F=B0=E5=B0=8E=E8=87=B4=E9=A0=81=E9=9D=A2?= =?UTF-8?q?=E5=B4=A9=E6=BD=B0=E8=88=87=E8=B6=8A=E6=AC=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 列表與操作紀錄查詢加上 whereHas('machine'),依 machine_user 授權過濾,客戶帳號只看得到可存取機台的資料(系統管理員不受影響) 2. pickup_code_logs.machine_id 可為 null,該紀錄查詢改為「machine_id 為 null 或機台可存取」以保留非機台紀錄 3. destroyPickupCode/destroyPassCode/destroyWelcomeGift 加上機台授權守衛,非系統管理員越權刪除回傳 403 4. tab-list blade 將 $x->machine->name 等改為 null-safe,作為縱深防禦 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Controllers/Admin/SalesController.php | 45 ++++++++++++++++--- .../pass-codes/partials/tab-list.blade.php | 4 +- .../pickup-codes/partials/tab-list.blade.php | 10 ++--- .../welcome-gifts/partials/tab-list.blade.php | 4 +- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/Admin/SalesController.php b/app/Http/Controllers/Admin/SalesController.php index e328e4c..ff536d3 100644 --- a/app/Http/Controllers/Admin/SalesController.php +++ b/app/Http/Controllers/Admin/SalesController.php @@ -194,7 +194,10 @@ class SalesController extends Controller // 1. 取貨碼列表 (list) if (!$isAjax || $tab === 'list') { - $query = PickupCode::with(['machine.slots.product', 'creator', 'order'])->latest(); + // 僅顯示目前帳號可存取機台的取貨碼(機台授權以 machine_user 為準,whereHas 會套用 Machine 的 machine_access 全域 scope) + $query = PickupCode::with(['machine.slots.product', 'creator', 'order']) + ->whereHas('machine') + ->latest(); if ($request->search) { $query->where(function ($q) use ($request) { @@ -219,7 +222,12 @@ class SalesController extends Controller // 2. 操作紀錄 (logs) if (!$isAjax || $tab === 'logs') { - $logQuery = PickupCodeLog::with(['user:id,name', 'machine:id,name,serial_no', 'pickupCode', 'order']); + // 同上:操作紀錄只顯示可存取機台的資料(machine_id 為 null 的非機台紀錄仍保留) + $logQuery = PickupCodeLog::with(['user:id,name', 'machine:id,name,serial_no', 'pickupCode', 'order']) + ->where(function ($q) { + $q->whereNull('machine_id') + ->orWhereHas('machine'); + }); if ($request->filled('search_log')) { $search = $request->input('search_log'); @@ -362,6 +370,11 @@ class SalesController extends Controller */ public function destroyPickupCode(PickupCode $pickupCode) { + // 機台授權以 machine_user 為準:非系統管理員若無法存取該取貨碼所屬機台則拒絕 + if (!Auth::user()->isSystemAdmin() && !Machine::whereKey($pickupCode->machine_id)->exists()) { + abort(403); + } + $oldValues = $pickupCode->toArray(); $pickupCode->update(['status' => 'cancelled']); @@ -411,7 +424,10 @@ class SalesController extends Controller // 1. 通行碼列表 (list) if (!$isAjax || $tab === 'list') { - $query = PassCode::with(['machine', 'creator'])->latest(); + // 僅顯示目前帳號可存取機台的通行碼(機台授權以 machine_user 為準,whereHas 會套用 Machine 的 machine_access 全域 scope) + $query = PassCode::with(['machine', 'creator']) + ->whereHas('machine') + ->latest(); if ($request->search) { $query->where(function ($q) use ($request) { @@ -447,7 +463,9 @@ class SalesController extends Controller // 2. 操作紀錄 (logs) if (!$isAjax || $tab === 'logs') { - $logQuery = PassCodeLog::with(['user:id,name', 'machine:id,name,serial_no', 'passCode']); + // 同上:操作紀錄只顯示可存取機台的資料(pass_code_logs.machine_id 為 NOT NULL) + $logQuery = PassCodeLog::with(['user:id,name', 'machine:id,name,serial_no', 'passCode']) + ->whereHas('machine'); if ($request->filled('search_log')) { $search = $request->input('search_log'); @@ -587,6 +605,11 @@ class SalesController extends Controller */ public function destroyPassCode(PassCode $passCode) { + // 機台授權以 machine_user 為準:非系統管理員若無法存取該通行碼所屬機台則拒絕 + if (!Auth::user()->isSystemAdmin() && !Machine::whereKey($passCode->machine_id)->exists()) { + abort(403); + } + $oldValues = $passCode->toArray(); $passCode->update(['status' => 'disabled']); @@ -618,7 +641,10 @@ class SalesController extends Controller // 1. 來店禮列表 (list) if (!$isAjax || $tab === 'list') { - $query = WelcomeGift::with(['machine', 'creator'])->latest(); + // 僅顯示目前帳號可存取機台的來店禮(機台授權以 machine_user 為準,whereHas 會套用 Machine 的 machine_access 全域 scope) + $query = WelcomeGift::with(['machine', 'creator']) + ->whereHas('machine') + ->latest(); if ($request->search) { $query->where(function ($q) use ($request) { @@ -654,7 +680,9 @@ class SalesController extends Controller // 2. 操作紀錄 (logs) if (!$isAjax || $tab === 'logs') { - $logQuery = WelcomeGiftLog::with(['machine:id,name,serial_no', 'welcomeGift', 'order:id,order_no']); + // 同上:操作紀錄只顯示可存取機台的資料(welcome_gift_logs.machine_id 為 NOT NULL) + $logQuery = WelcomeGiftLog::with(['machine:id,name,serial_no', 'welcomeGift', 'order:id,order_no']) + ->whereHas('machine'); if ($request->filled('search_log')) { $search = $request->input('search_log'); @@ -846,6 +874,11 @@ class SalesController extends Controller */ public function destroyWelcomeGift(WelcomeGift $welcomeGift) { + // 機台授權以 machine_user 為準:非系統管理員若無法存取該來店禮所屬機台則拒絕 + if (!Auth::user()->isSystemAdmin() && !Machine::whereKey($welcomeGift->machine_id)->exists()) { + abort(403); + } + $oldValues = $welcomeGift->toArray(); $welcomeGift->update(['status' => 'disabled']); diff --git a/resources/views/admin/sales/pass-codes/partials/tab-list.blade.php b/resources/views/admin/sales/pass-codes/partials/tab-list.blade.php index b1543f7..ef79895 100644 --- a/resources/views/admin/sales/pass-codes/partials/tab-list.blade.php +++ b/resources/views/admin/sales/pass-codes/partials/tab-list.blade.php @@ -109,7 +109,7 @@
{{ $code->name }}
{{ - $code->machine->name }}
+ $code->machine?->name ?? '-' }} @if($code->expires_at) @@ -241,7 +241,7 @@ class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest mb-1"> {{ __('Machine') }}

{{ - $code->machine->name }}

+ $code->machine?->name ?? '-' }}

- {{ $code->machine->name }}
+ {{ $code->machine?->name ?? '-' }}
{{ - $code->machine->serial_no }}
+ $code->machine?->serial_no }} @php - $slot = $code->machine->slots->where('slot_no', $code->slot_no)->first(); + $slot = $code->machine?->slots->where('slot_no', $code->slot_no)->first(); $productName = $slot ? ($slot->product?->name ?? __('Empty')) : __('Empty'); @endphp
{{ @@ -251,7 +251,7 @@ @endif

- {{ $code->machine->name }} + {{ $code->machine?->name ?? '-' }}

@@ -287,7 +287,7 @@

{{ $code->slot_no }} @php - $slotMobile = $code->machine->slots->where('slot_no', + $slotMobile = $code->machine?->slots->where('slot_no', $code->slot_no)->first(); $prodMobile = $slotMobile ? ($slotMobile->product?->name ?? __('Empty')) : __('Empty'); diff --git a/resources/views/admin/sales/welcome-gifts/partials/tab-list.blade.php b/resources/views/admin/sales/welcome-gifts/partials/tab-list.blade.php index 9655d27..84dbd89 100644 --- a/resources/views/admin/sales/welcome-gifts/partials/tab-list.blade.php +++ b/resources/views/admin/sales/welcome-gifts/partials/tab-list.blade.php @@ -108,7 +108,7 @@

{{ $gift->name }}
{{ - $gift->machine->name }}
+ $gift->machine?->name ?? '-' }} @@ -258,7 +258,7 @@

{{ __('Machine') }}

- {{ $gift->machine->name }}

+ {{ $gift->machine?->name ?? '-' }}