Files
device-management/app/Http/Controllers/DeviceController.php
T
Wian Drs 1e80be180e
tests / ci (push) Has been cancelled
Initial commit device-management
2026-08-25 09:42:00 +07:00

173 lines
7.3 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\SystemRole;
use App\Http\Requests\StoreDeviceRequest;
use App\Http\Requests\UpdateDeviceRequest;
use App\Models\Device;
use App\Models\DeviceCredential;
use App\Models\DeviceModel;
use App\Models\DeviceType;
use App\Models\DeviceVendor;
use App\Models\TenantDevicePolicy;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;
class DeviceController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): Response
{
$this->ensureTenantAccount();
abort_unless($request->user()->can('device.view'), 403);
$devices = Device::query()->with(['vendor:id,name', 'type:id,name', 'model:id,name', 'creator:id,name'])->withCount('userAssignments')
->when($request->string('search')->isNotEmpty(), fn ($query) => $query->where(fn ($nested) => $nested
->where('name', 'ilike', '%'.$request->string('search').'%')
->orWhere('management_address', 'ilike', '%'.$request->string('search').'%')
->orWhere('location', 'ilike', '%'.$request->string('search').'%')))
->when($request->integer('vendor'), fn ($query, $vendor) => $query->where('device_vendor_id', $vendor))
->when($request->string('status')->isNotEmpty(), fn ($query) => $query->where('status', $request->string('status')))
->latest()->paginate(15)->withQueryString();
return Inertia::render('devices/index', ['devices' => $devices, 'vendors' => DeviceVendor::where('is_active', true)->get(['id', 'name']), 'filters' => $request->only('search', 'vendor', 'status'), 'policy' => $this->policy(), 'isTenantAdmin' => $request->user()->hasRole(SystemRole::TenantAdmin->value)]);
}
/**
* Show the form for creating a new resource.
*/
public function create(): Response
{
$this->authorizeCreate();
return Inertia::render('devices/form', $this->catalog() + ['device' => null]);
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreDeviceRequest $request): RedirectResponse
{
$this->authorizeCreate();
$this->validateModelCombination($request);
$data = $request->validated();
$username = $data['initial_username'];
$password = $data['initial_password'] ?? '';
$enablePassword = $data['initial_enable_password'] ?? null;
unset($data['initial_username'], $data['initial_password'], $data['initial_enable_password']);
DB::transaction(function () use ($data, $username, $password, $enablePassword, $request): void {
$device = Device::create($data + ['tenant_id' => $request->user()->tenant_id, 'created_by' => $request->user()->id, 'updated_by' => $request->user()->id]);
DeviceCredential::create([
'tenant_id' => $request->user()->tenant_id, 'device_id' => $device->id,
'name' => 'Login Awal', 'username' => $username, 'password' => $password,
'enable_password' => $enablePassword,
'connection_type' => $device->connection_type, 'privilege_type' => 'master',
'is_master' => true, 'is_active' => true,
'created_by' => $request->user()->id, 'updated_by' => $request->user()->id,
]);
});
return to_route('devices.index')->with('success', 'Perangkat berhasil ditambahkan.');
}
/**
* Display the specified resource.
*/
public function show(Device $device): Response
{
$this->ensureOwnedDevice($device);
abort_unless(request()->user()->can('device.view'), 403);
return Inertia::render('devices/show', [
'device' => $device->load(['vendor:id,name,slug', 'type:id,name', 'model:id,name', 'creator:id,name']),
'credentials' => request()->user()->can('device.credential.view')
? $device->credentials()->get(['id', 'name', 'username', 'connection_type', 'privilege_type', 'is_master', 'is_active', 'last_verified_at'])
: [],
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Device $device): Response
{
$this->ensureOwnedDevice($device);
$this->authorizeUpdate($device);
return Inertia::render('devices/form', $this->catalog() + ['device' => $device]);
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateDeviceRequest $request, Device $device): RedirectResponse
{
$this->ensureOwnedDevice($device);
$this->authorizeUpdate($device);
$this->validateModelCombination($request);
$device->update($request->validated() + ['updated_by' => $request->user()->id]);
return to_route('devices.show', $device)->with('success', 'Perangkat berhasil diperbarui.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Device $device): RedirectResponse
{
$this->ensureOwnedDevice($device);
abort_unless(request()->user()->can('device.delete'), 403);
abort_if(request()->user()->hasRole(SystemRole::TenantUser->value) && (! $this->policy()->tenant_user_can_delete_own || $device->created_by !== request()->user()->id), 403);
$device->delete();
return to_route('devices.index')->with('success', 'Perangkat berhasil dihapus.');
}
private function catalog(): array
{
return ['vendors' => DeviceVendor::where('is_active', true)->get(['id', 'name', 'slug']), 'types' => DeviceType::where('is_active', true)->get(['id', 'name']), 'models' => DeviceModel::where('is_active', true)->get(['id', 'name', 'device_vendor_id', 'device_type_id'])];
}
private function policy(): TenantDevicePolicy
{
return TenantDevicePolicy::firstOrCreate(['tenant_id' => request()->user()->tenant_id]);
}
private function ensureTenantAccount(): void
{
abort_if(request()->user()->is_platform_admin || ! request()->user()->tenant_id, 403);
}
private function ensureOwnedDevice(Device $device): void
{
$this->ensureTenantAccount();
abort_unless($device->tenant_id === request()->user()->tenant_id, 404);
}
private function authorizeCreate(): void
{
$this->ensureTenantAccount();
abort_unless(request()->user()->can('device.create'), 403);
abort_if(request()->user()->hasRole(SystemRole::TenantUser->value) && ! $this->policy()->tenant_user_can_create, 403);
}
private function authorizeUpdate(Device $device): void
{
abort_unless(request()->user()->can('device.update'), 403);
abort_if(request()->user()->hasRole(SystemRole::TenantUser->value) && (! $this->policy()->tenant_user_can_update_own || $device->created_by !== request()->user()->id), 403);
}
private function validateModelCombination(Request $request): void
{
if ($request->filled('device_model_id')) {
abort_unless(DeviceModel::whereKey($request->integer('device_model_id'))->where('device_vendor_id', $request->integer('device_vendor_id'))->where('device_type_id', $request->integer('device_type_id'))->exists(), 422, 'Model tidak sesuai dengan vendor dan tipe perangkat.');
}
}
}