173 lines
7.3 KiB
PHP
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.');
|
|
}
|
|
}
|
|
}
|