Files
device-management/app/Jobs/SyncDeviceUser.php
T
Wian Drs 60946ddf37
tests / ci (push) Has been cancelled
update lisensi prosess
2026-08-25 13:43:55 +07:00

169 lines
11 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\DeviceUserAssignment;
use App\Models\TenantDeviceSetting;
use App\Network\Clients\Hisfocus\HisfocusSshClient;
use App\Network\Clients\Hisfocus\HisfocusWebClient;
use App\Network\Clients\Hsgq\HsgqSshClient;
use App\Network\Clients\Hsgq\HsgqTelnetClient;
use App\Network\Clients\Hsgq\HsgqWebClient;
use App\Network\Clients\RouterOs\RouterOsApiClient;
use App\Network\Clients\Zte\ZteSshClient;
use App\Network\Drivers\Hisfocus\HisfocusOltDriver;
use App\Network\Drivers\Hsgq\HsgqOltDriver;
use App\Network\Drivers\Mikrotik\MikrotikDriver;
use App\Network\Drivers\Zte\ZteC3xxDriver;
use App\Services\LicenseEntitlementService;
use App\Support\TenantContext;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;
class SyncDeviceUser implements ShouldQueue
{
use Queueable;
public int $tries = 1;
public function __construct(public readonly int $tenantId, public readonly int $assignmentId) {}
public function handle(TenantContext $context): void
{
$context->set($this->tenantId);
setPermissionsTeamId($this->tenantId);
try {
if (! app(LicenseEntitlementService::class)->allowsUse($this->tenantId)) {
DeviceUserAssignment::withoutGlobalScope('tenant')->whereKey($this->assignmentId)->update(['sync_status' => 'pending', 'error_code' => 'LICENSE_INACTIVE', 'message' => 'Menunggu lisensi tenant aktif.']);
return;
}
$assignment = DeviceUserAssignment::with(['device.vendor', 'device.credentials', 'accessUser'])->find($this->assignmentId);
if (! $assignment || $assignment->tenant_id !== $this->tenantId) {
return;
}
$mikrotik = $assignment->device->vendor->slug === 'mikrotik' && $assignment->device->hasConnection('routeros_api');
$zte = $assignment->device->vendor->slug === 'zte' && $assignment->device->hasConnection('ssh');
$hsgq = $assignment->device->vendor->slug === 'hsgq' && ($assignment->device->hasConnection('ssh') || $assignment->device->hasConnection('telnet'));
$hisfocus = $assignment->device->vendor->slug === 'hisfocus' && ($assignment->device->hasConnection('ssh') || $assignment->device->hasConnection('telnet'));
if (! $mikrotik && ! $zte && ! $hsgq && ! $hisfocus) {
$assignment->update(['sync_status' => 'unsupported', 'error_code' => 'DRIVER_NOT_AVAILABLE', 'message' => 'Driver user perangkat belum tersedia untuk vendor ini.']);
return;
}
$setting = TenantDeviceSetting::where('tenant_id', $this->tenantId)->first();
if (! $setting) {
$assignment->update(['sync_status' => 'pending', 'error_code' => 'BASE_SETTING_REQUIRED', 'message' => 'Menunggu Base User perangkat dikonfigurasi.']);
return;
}
$credential = $assignment->device->credentials->where('is_active', true)->sortByDesc('is_master')->first();
if (! $credential) {
$assignment->update(['sync_status' => 'pending', 'error_code' => 'CREDENTIAL_REQUIRED', 'message' => 'Menunggu credential aktif perangkat.']);
return;
}
$assignment->update(['sync_status' => 'processing', 'attempts' => $assignment->attempts + 1, 'last_attempted_at' => now(), 'error_code' => null, 'message' => null]);
$mikrotikDriver = $mikrotik
? new MikrotikDriver(new RouterOsApiClient($assignment->device->management_address, $assignment->device->portFor('routeros_api'), $credential->username, $credential->password, $setting->connection_timeout, $setting->use_tls, $setting->verify_tls))
: null;
$zteDriver = $zte
? new ZteC3xxDriver(new ZteSshClient($assignment->device->management_address, $assignment->device->portFor('ssh'), $setting->connection_timeout))
: null;
$hsgqDriver = $hsgq
? new HsgqOltDriver(
$assignment->device->hasConnection('ssh')
? new HsgqSshClient($assignment->device->management_address, $assignment->device->portFor('ssh'), $setting->connection_timeout)
: new HsgqTelnetClient($assignment->device->management_address, $assignment->device->portFor('telnet'), $setting->connection_timeout),
$assignment->device->hasConnection('ssh') && $assignment->device->hasConnection('telnet')
? new HsgqTelnetClient($assignment->device->management_address, $assignment->device->portFor('telnet'), $setting->connection_timeout)
: null,
new HsgqWebClient($assignment->device->management_address, $setting->connection_timeout),
)
: null;
$hisfocusDriver = $hisfocus
? new HisfocusOltDriver($assignment->device->hasConnection('telnet')
? new HsgqTelnetClient($assignment->device->management_address, $assignment->device->portFor('telnet'), $setting->connection_timeout)
: new HisfocusSshClient($assignment->device->management_address, $assignment->device->portFor('ssh'), $setting->connection_timeout))
: null;
$hisfocusWeb = $hisfocus
&& $assignment->device->hasConnection('web_http') ? new HisfocusWebClient(
$assignment->device->management_address,
$assignment->device->portFor('web_http'),
$setting->connection_timeout,
)
: null;
if ($assignment->desired_operation === 'delete') {
if ($mikrotik) {
$mikrotikDriver->deleteUser($assignment->remote_username ?: $assignment->accessUser->username);
} elseif ($zte) {
$zteDriver->deleteAccessUser($credential->username, $credential->password, $credential->enable_password, $assignment->remote_username ?: $assignment->accessUser->username);
} elseif ($hsgq) {
$hsgqDriver->deleteUser($credential->password, $credential->enable_password, $assignment->remote_username ?: $assignment->accessUser->username);
} else {
$hisfocusDriver->deleteUser($credential->username, $credential->password, $credential->enable_password, $assignment->remote_username ?: $assignment->accessUser->username);
$webUsername = $assignment->remote_username ?: $assignment->accessUser->username;
if ($hisfocusWeb && isset($hisfocusWeb->users($credential->username, $credential->password)[$webUsername])) {
$hisfocusWeb->deleteUser($credential->username, $credential->password, $webUsername);
}
}
$accessUser = $assignment->accessUser;
$assignment->delete();
if ($accessUser->trashed() && ! $accessUser->assignments()->exists()) {
$accessUser->forceDelete();
}
return;
} else {
if ($assignment->remote_username && $assignment->remote_username !== $assignment->accessUser->username) {
if ($mikrotik) {
$mikrotikDriver->deleteUser($assignment->remote_username);
} elseif ($zte) {
$zteDriver->deleteAccessUser($credential->username, $credential->password, $credential->enable_password, $assignment->remote_username);
} elseif ($hsgq) {
$hsgqDriver->deleteUser($credential->password, $credential->enable_password, $assignment->remote_username);
} else {
$hisfocusDriver->deleteUser($credential->username, $credential->password, $credential->enable_password, $assignment->remote_username);
if ($hisfocusWeb && isset($hisfocusWeb->users($credential->username, $credential->password)[$assignment->remote_username])) {
$hisfocusWeb->deleteUser($credential->username, $credential->password, $assignment->remote_username);
}
}
}
if ($mikrotik) {
$result = $mikrotikDriver->syncUser($assignment->accessUser->username, $assignment->accessUser->password, $assignment->group_name, $assignment->accessUser->is_enabled);
} elseif ($zte) {
$result = $zteDriver->syncUser($credential->username, $credential->password, $credential->enable_password, $assignment->accessUser->username, $assignment->accessUser->password, $assignment->group_name, $assignment->accessUser->is_enabled);
} elseif ($hsgq) {
$result = $hsgqDriver->syncUser($credential->password, $credential->enable_password, $assignment->accessUser->username, $assignment->accessUser->password, $assignment->group_name, $assignment->accessUser->is_enabled);
} else {
$result = $hisfocusDriver->syncUser($credential->username, $credential->password, $credential->enable_password, $assignment->accessUser->username, $assignment->accessUser->password, $assignment->group_name, $assignment->accessUser->is_enabled);
if ($hisfocusWeb) {
$webRoles = ['RADIQ-NOC' => 'Administrator', 'RADIQ-WRITE' => 'Operator', 'RADIQ-READ' => 'Guest'];
$webUsers = $hisfocusWeb->users($credential->username, $credential->password);
if (isset($webUsers[$assignment->accessUser->username])) {
$hisfocusWeb->deleteUser($credential->username, $credential->password, $assignment->accessUser->username);
}
if ($assignment->accessUser->is_enabled) {
$hisfocusWeb->addUser($credential->username, $credential->password, $assignment->accessUser->username, $assignment->accessUser->password, $webRoles[$assignment->group_name]);
}
}
}
}
$assignment->update(['sync_status' => 'synced', 'remote_id' => $result['remote_id'] ?? $assignment->remote_id, 'remote_username' => $assignment->accessUser->username, 'last_synced_at' => now(), 'error_code' => null, 'message' => 'Sinkronisasi berhasil.']);
$assignment->device->update(['status' => 'online', 'last_seen_at' => now()]);
} catch (Throwable $exception) {
report($exception);
$code = str($exception->getMessage())->before(':')->limit(64)->toString();
$pending = in_array($code, ['DEVICE_UNREACHABLE', 'CONNECTION_TIMEOUT', 'CREDENTIAL_REQUIRED'], true);
DeviceUserAssignment::whereKey($this->assignmentId)->update(['sync_status' => $pending ? 'pending' : 'failed', 'error_code' => $code ?: 'UNKNOWN_ERROR', 'message' => $pending ? 'Perangkat belum dapat dijangkau; akan dicoba kembali.' : 'Sinkronisasi gagal tanpa membuka data sensitif.']);
if ($pending) {
DeviceUserAssignment::whereKey($this->assignmentId)->first()?->device()->update(['status' => 'offline']);
}
} finally {
$context->clear();
setPermissionsTeamId(null);
}
}
}