改进 移除设备

This commit is contained in:
iVampireSP.com 2023-01-19 23:09:01 +08:00
parent 9145d1cee1
commit c306393a19
No known key found for this signature in database
GPG Key ID: 2F7B001CA27A8132
5 changed files with 111 additions and 29 deletions

View File

@ -4,6 +4,7 @@
use App\Exceptions\EmqxSupportException; use App\Exceptions\EmqxSupportException;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Jobs\Support\EMQXKickClientJob;
use App\Support\EmqxSupport; use App\Support\EmqxSupport;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -38,16 +39,22 @@ public function index(Request $request): RedirectResponse|View
// return view('admin.device.show', compact('client')); // return view('admin.device.show', compact('client'));
// } // }
public function destroy(Request $request): RedirectResponse
/**
* @throws EmqxSupportException
*/
public function destroy($client_id): RedirectResponse
{ {
$emqx = new EmqxSupport(); $emqx = new EmqxSupport();
$emqx->kickClient($client_id); if ($request->filled('client_id')) {
$emqx->kickClient($request->input('client_id'));
}
return back()->with('success', '此客户端已下线。'); if ($request->filled('username')) {
$username = $request->input('username');
$module_name = explode('.', $username)[0];
$this->dispatch(new EMQXKickClientJob(null, $module_name, false));
$this->dispatch(new EMQXKickClientJob(null, $module_name . '.', true));
}
return back()->with('success', '正在让它们下线。');
} }
} }

View File

@ -0,0 +1,76 @@
<?php
namespace App\Jobs\Support;
use App\Exceptions\EmqxSupportException;
use App\Support\EmqxSupport;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class EMQXKickClientJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected string|null $client_id, $username;
protected bool $like_username;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($client_id, $username, $like_username = false)
{
$this->client_id = $client_id;
$this->username = $username;
$this->like_username = $like_username;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(): void
{
$emqx = new EmqxSupport();
if ($this->client_id) {
$emqx->api()->delete('/clients/' . $this->client_id);
}
if ($this->username) {
$query = 'username';
if ($this->like_username) {
$query = 'like_username';
}
try {
$clients = $emqx->clients([$query => $this->username]);
} catch (EmqxSupportException $e) {
Log::error('emqx connect failed.', [$e]);
return;
}
if ($clients) {
// 循环翻页
for ($i = 1; $i <= $clients['meta']['count']; $i++) {
try {
$clients = $emqx->clients([$query => $this->username, 'page' => $i]);
} catch (EmqxSupportException $e) {
Log::error('emqx connect failed.', [$e]);
continue;
}
foreach ($clients['data'] as $client) {
dispatch(new self($client['clientid'], null));
}
}
}
}
}
}

View File

@ -3,6 +3,7 @@
namespace App\Support; namespace App\Support;
use App\Exceptions\EmqxSupportException; use App\Exceptions\EmqxSupportException;
use App\Jobs\Support\EMQXKickClientJob;
use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\PendingRequest; use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
@ -11,9 +12,9 @@
class EmqxSupport class EmqxSupport
{ {
/** /**
* @throws EmqxSupportException * 移除客户端
*/ */
public function kickClient($client_id = null, $username = null): void public function kickClient($client_id = null, $username = null, bool $like_username = false): void
{ {
// 如果都为空,直接返回 // 如果都为空,直接返回
if (empty($client_id) && empty($username)) { if (empty($client_id) && empty($username)) {
@ -25,26 +26,11 @@ public function kickClient($client_id = null, $username = null): void
} }
if ($username) { if ($username) {
try { dispatch(new EMQXKickClientJob(null, $username, $like_username));
$clients = $this->clients(['username' => $username]);
} catch (EmqxSupportException $e) {
throw new EmqxSupportException($e->getMessage());
}
if ($clients) {
// 循环翻页
for ($i = 1; $i <= $clients['meta']['count']; $i++) {
$clients = $this->clients(['username' => $username, 'page' => $i]);
foreach ($clients['data'] as $client) {
$this->api()->delete('/clients/' . $client['clientid']);
}
}
}
} }
} }
private function api(): PendingRequest public function api(): PendingRequest
{ {
return Http::baseUrl(config('emqx.api_url'))->withBasicAuth(config('emqx.api_key'), config('emqx.api_secret')); return Http::baseUrl(config('emqx.api_url'))->withBasicAuth(config('emqx.api_key'), config('emqx.api_secret'));
} }

View File

@ -70,15 +70,26 @@
@if ($c['subscriptions_cnt'] > 0) @if ($c['subscriptions_cnt'] > 0)
<span class="text-success">{{ $c['subscriptions_cnt'] }} </span> <span class="text-success">{{ $c['subscriptions_cnt'] }} </span>
@else @else
<span class="text-danger">没有</span> <span class="text-danger">没有订阅</span>
@endif @endif
</td> </td>
<td> <td>
<form action="{{ route('admin.devices.destroy', $c['clientid']) }}" method="post"> <form action="{{ route('admin.devices.destroy') }}" method="post">
@csrf @csrf
@method('DELETE') @method('DELETE')
<input type="hidden" name="client_id" value="{{ $c['clientid'] }}">
<button type="submit" class="btn btn-danger btn-sm">踢出</button> <button type="submit" class="btn btn-danger btn-sm">踢出</button>
</form> </form>
<form class="mt-2" action="{{ route('admin.devices.destroy') }}" method="post"
onsubmit="return confirm('将踢出此模块以及它的所有客户端。')">
@csrf
@method('DELETE')
<input type="hidden" name="username" value="{{ $c['username'] }}">
<input type="hidden" name="like_username" value="1"/>
<button type="submit" class="btn btn-danger btn-sm">踢出所有</button>
</form>
</td> </td>
</tr> </tr>
@endforeach @endforeach

View File

@ -47,7 +47,9 @@
Route::resource('user-groups', UserGroupController::class); Route::resource('user-groups', UserGroupController::class);
Route::resource('devices', DeviceController::class)->only(['index', 'destroy']); Route::get('devices', [DeviceController::class, 'index'])->name('devices.index');
Route::delete('devices', [DeviceController::class, 'destroy'])->name('devices.destroy');
Route::resource('notifications', NotificationController::class)->only(['create', 'store']); Route::resource('notifications', NotificationController::class)->only(['create', 'store']);