169 lines
11 KiB
PHP
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);
|
|
}
|
|
}
|
|
}
|