[FEAT] 優化帳號管理授權顯示邏輯與 UI 樣式一致性
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 59s

This commit is contained in:
2026-03-23 17:16:26 +08:00
parent 72812f9b0b
commit 38770b080b
26 changed files with 1265 additions and 444 deletions

View File

@@ -45,7 +45,7 @@ class MachineSettingController extends AdminController
// 3. 基礎下拉資料 (用於新增/編輯機台的彈窗)
$models = MachineModel::select('id', 'name')->get();
$paymentConfigs = PaymentConfig::select('id', 'name')->get();
$companies = \App\Models\System\Company::select('id', 'name')->get();
$companies = \App\Models\System\Company::select('id', 'name', 'code')->get();
return view('admin.basic-settings.machines.index', compact(
'machines',
@@ -101,7 +101,7 @@ class MachineSettingController extends AdminController
{
$models = MachineModel::select('id', 'name')->get();
$paymentConfigs = PaymentConfig::select('id', 'name')->get();
$companies = \App\Models\System\Company::select('id', 'name')->get();
$companies = \App\Models\System\Company::select('id', 'name', 'code')->get();
return view('admin.basic-settings.machines.edit', compact('machine', 'models', 'paymentConfigs', 'companies'));
}
@@ -137,6 +137,13 @@ class MachineSettingController extends AdminController
'payment_config_id' => 'nullable|exists:payment_configs,id',
'location' => 'nullable|string|max:255',
]);
// 僅限系統管理員可修改公司
if (auth()->user()->isSystemAdmin()) {
$companyRule = ['company_id' => 'nullable|exists:companies,id'];
$companyData = $request->validate($companyRule);
$validated = array_merge($validated, $companyData);
}
Log::info('Machine Update Validated Data', ['data' => $validated]);
} catch (\Illuminate\Validation\ValidationException $e) {

View File

@@ -38,7 +38,7 @@ class PaymentConfigController extends AdminController
*/
public function create(): View
{
$companies = \App\Models\System\Company::select('id', 'name')->get();
$companies = \App\Models\System\Company::select('id', 'name', 'code')->get();
return view('admin.basic-settings.payment-configs.create', compact('companies'));
}

View File

@@ -67,12 +67,68 @@ class MachineController extends AdminController
return view('admin.machines.logs', compact('logs', 'machines'));
}
/**
* 機台權限設定 (開發中)
* AJAX: 取得特定帳號的機台分配狀態
*/
public function permissions(Request $request): View
public function getAccountMachines(\App\Models\System\User $user)
{
return view('admin.machines.index', ['machines' => Machine::paginate(1)]); // Placeholder
$currentUser = auth()->user();
// 安全檢查:只能操作自己公司的帳號(除非是系統管理員)
if (!$currentUser->isSystemAdmin() && $user->company_id !== $currentUser->company_id) {
return response()->json(['error' => 'Unauthorized'], 403);
}
// 取得該公司所有機台 (限定 company_id 以實作資料隔離)
$machines = Machine::where('company_id', $user->company_id)
->get(['id', 'name', 'serial_no']);
$assignedIds = $user->machines()->pluck('machines.id')->toArray();
return response()->json([
'user' => $user,
'machines' => $machines,
'assigned_ids' => $assignedIds
]);
}
/**
* AJAX: 儲存特定帳號的機台分配
*/
public function syncAccountMachines(Request $request, \App\Models\System\User $user)
{
$currentUser = auth()->user();
// 安全檢查
if (!$currentUser->isSystemAdmin() && $user->company_id !== $currentUser->company_id) {
return response()->json(['error' => 'Unauthorized'], 403);
}
$request->validate([
'machine_ids' => 'nullable|array',
'machine_ids.*' => 'exists:machines,id'
]);
// 加固驗證:確保所有機台 ID 都屬於該使用者的公司
if ($request->has('machine_ids')) {
$machineIds = array_unique($request->machine_ids);
$validCount = Machine::where('company_id', $user->company_id)
->whereIn('id', $machineIds)
->count();
if ($validCount !== count($machineIds)) {
return response()->json(['error' => 'Invalid machine IDs provided.'], 422);
}
}
$user->machines()->sync($request->machine_ids ?? []);
return response()->json([
'success' => true,
'message' => __('Permissions updated successfully.'),
'assigned_machines' => $user->machines()->select('machines.id', 'machines.name', 'machines.serial_no')->get()
]);
}
/**

View File

@@ -248,7 +248,7 @@ class PermissionController extends Controller
// 帳號管理
public function accounts(Request $request)
{
$query = \App\Models\System\User::query()->with(['company', 'roles']);
$query = \App\Models\System\User::query()->with(['company', 'roles', 'machines']);
// 租戶隔離:如果不是系統管理員,則只看自己公司的成員
if (!auth()->user()->isSystemAdmin()) {

View File

@@ -12,6 +12,26 @@ class Machine extends Model
use HasFactory, TenantScoped;
use \Illuminate\Database\Eloquent\SoftDeletes;
protected static function booted()
{
// 權限隔離:一般帳號登入時只能看到自己被分配的機台
static::addGlobalScope('machine_access', function (\Illuminate\Database\Eloquent\Builder $builder) {
$user = auth()->user();
// 如果是在 Console、或是系統管理員、或是租戶的「管理員」角色則不限制 (可看該公司所有機台)
if (app()->runningInConsole() || !$user || $user->isSystemAdmin() || $user->hasRole('管理員') || $user->hasRole('super-admin')) {
return;
}
// 一般租戶帳號:限制只能看自己擁有的機台
$builder->whereExists(function ($query) use ($user) {
$query->select(\Illuminate\Support\Facades\DB::raw(1))
->from('machine_user')
->whereColumn('machine_user.machine_id', 'machines.id')
->where('machine_user.user_id', $user->id);
});
});
}
protected $fillable = [
'company_id',
'name',
@@ -101,4 +121,8 @@ class Machine extends Model
return $this->belongsTo(\App\Models\System\User::class, 'updater_id');
}
public function users()
{
return $this->belongsToMany(\App\Models\System\User::class);
}
}

View File

@@ -69,6 +69,14 @@ class User extends Authenticatable
return $this->belongsTo(Company::class);
}
/**
* Get the machines assigned to the user.
*/
public function machines()
{
return $this->belongsToMany(\App\Models\Machine\Machine::class);
}
/**
* Check if the user is a system administrator.
*/