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); } } }