113 lines
4.3 KiB
PHP
113 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace App\Network\Clients\Hisfocus;
|
|
|
|
use Illuminate\Http\Client\PendingRequest;
|
|
use Illuminate\Support\Facades\Http;
|
|
use RuntimeException;
|
|
|
|
class HisfocusWebClient
|
|
{
|
|
public function __construct(private readonly string $host, private readonly int $port = 80, private readonly int $timeout = 10) {}
|
|
|
|
/** @return array<string, string> */
|
|
public function users(string $loginUsername, string $loginPassword): array
|
|
{
|
|
$match = null;
|
|
for ($attempt = 1; $attempt <= 3; $attempt++) {
|
|
$body = $this->request($loginUsername, $loginPassword)->get($this->url('/userOverview.asp'))->body();
|
|
if (preg_match('/var\s+userList\s*=\s*new\s+Array\((.*?)\);/s', $body, $found)) {
|
|
$match = $found;
|
|
break;
|
|
}
|
|
if ($attempt < 3) {
|
|
usleep(250_000);
|
|
}
|
|
}
|
|
if (! $match) {
|
|
throw new RuntimeException('HISFOCUS_WEB_PARSE_FAILED: daftar user WebGUI tidak dikenali setelah tiga percobaan.');
|
|
}
|
|
preg_match_all('/"([^"]*)"/', $match[1], $values);
|
|
$users = [];
|
|
foreach (array_chunk($values[1], 2) as $user) {
|
|
if (count($user) === 2) {
|
|
$users[$user[0]] = $user[1];
|
|
}
|
|
}
|
|
|
|
return $users;
|
|
}
|
|
|
|
public function addUser(string $loginUsername, string $loginPassword, string $username, string $password, string $group): void
|
|
{
|
|
$response = $this->request($loginUsername, $loginPassword)->asForm()->post($this->url('/goform/setAddUser'), [
|
|
'addUserHiddenId' => 0,
|
|
'UserName' => $username,
|
|
'UserGroup' => $group,
|
|
'UserPassword' => $password,
|
|
'ComfirmPassword' => $password,
|
|
]);
|
|
$this->assertAccepted($response->status(), $response->body());
|
|
$this->assertUserState($loginUsername, $loginPassword, $username, $group);
|
|
}
|
|
|
|
public function changePassword(string $loginUsername, string $loginPassword, string $username, string $oldPassword, string $newPassword): void
|
|
{
|
|
$response = $this->request($loginUsername, $loginPassword)->asForm()->post($this->url('/goform/setUserPassword'), [
|
|
'HiddenUserName' => $username,
|
|
'LYS' => $oldPassword,
|
|
'PBT' => $newPassword,
|
|
]);
|
|
$this->assertAccepted($response->status(), $response->body());
|
|
}
|
|
|
|
public function deleteUser(string $loginUsername, string $loginPassword, string $username): void
|
|
{
|
|
$response = $this->request($loginUsername, $loginPassword)->asForm()->post($this->url('/goform/setDeleteUser'), [
|
|
'user'.$username.'DeleteCheck' => 'on',
|
|
]);
|
|
$this->assertAccepted($response->status(), $response->body());
|
|
$this->assertUserState($loginUsername, $loginPassword, $username, null);
|
|
}
|
|
|
|
public function canLogin(string $username, string $password): bool
|
|
{
|
|
return $this->request($username, $password)->get($this->url('/'))->successful();
|
|
}
|
|
|
|
private function request(string $username, string $password): PendingRequest
|
|
{
|
|
return Http::withBasicAuth($username, $password)->timeout($this->timeout)->connectTimeout($this->timeout);
|
|
}
|
|
|
|
private function assertAccepted(int $status, string $body): void
|
|
{
|
|
if ($status >= 400 || stripos($body, 'Access Denied') !== false) {
|
|
throw new RuntimeException('HISFOCUS_WEB_REJECTED: WebGUI menolak operasi user.');
|
|
}
|
|
}
|
|
|
|
private function assertUserState(string $loginUsername, string $loginPassword, string $username, ?string $expectedGroup): void
|
|
{
|
|
for ($attempt = 1; $attempt <= 4; $attempt++) {
|
|
$users = $this->users($loginUsername, $loginPassword);
|
|
$exists = array_key_exists($username, $users);
|
|
if ($expectedGroup === null ? ! $exists : ($exists && strcasecmp($users[$username], $expectedGroup) === 0)) {
|
|
return;
|
|
}
|
|
if ($attempt < 4) {
|
|
usleep(250_000);
|
|
}
|
|
}
|
|
|
|
throw new RuntimeException($expectedGroup === null
|
|
? 'HISFOCUS_WEB_DELETE_FAILED: user masih tercatat di WebGUI.'
|
|
: 'HISFOCUS_WEB_ADD_FAILED: user atau role belum tercatat di WebGUI.');
|
|
}
|
|
|
|
private function url(string $path): string
|
|
{
|
|
return "http://{$this->host}:{$this->port}{$path}";
|
|
}
|
|
}
|