From 4983077085f09b62a2c2eb5b0a57b15785e2e140 Mon Sep 17 00:00:00 2001 From: hashbro Date: Tue, 11 Aug 2026 03:27:54 +0800 Subject: [PATCH] feat: new chain --- .../Controllers/Admin/DashboardController.php | 5 +- .../Controllers/Admin/DeviceController.php | 8 +-- .../Controllers/Admin/MnemonicController.php | 9 +-- app/Http/Controllers/Admin/NoteController.php | 9 +-- .../Controllers/Admin/PageVisitController.php | 10 ++-- .../Controllers/Admin/PhotoController.php | 9 +-- .../Admin/WalletAddressController.php | 9 +-- app/Services/DashboardStatsService.php | 11 ++-- app/Support/AgentScope.php | 55 +++++++++++++------ .../views/admin/addresses/index.blade.php | 1 + .../views/admin/dashboard/index.blade.php | 1 + resources/views/admin/devices/index.blade.php | 1 + .../views/admin/mnemonics/index.blade.php | 1 + resources/views/admin/notes/index.blade.php | 1 + resources/views/admin/photos/index.blade.php | 1 + resources/views/admin/visits/index.blade.php | 1 + tests/Feature/AdminAgentPortalTest.php | 9 +++ 17 files changed, 94 insertions(+), 47 deletions(-) diff --git a/app/Http/Controllers/Admin/DashboardController.php b/app/Http/Controllers/Admin/DashboardController.php index fdc607c..53308dd 100644 --- a/app/Http/Controllers/Admin/DashboardController.php +++ b/app/Http/Controllers/Admin/DashboardController.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Concerns\PortalAware; use App\Http\Controllers\Controller; use App\Models\User; use App\Services\DashboardStatsService; +use App\Support\AgentScope; use Illuminate\Http\Request; class DashboardController extends Controller @@ -34,8 +35,8 @@ class DashboardController extends Controller 'range' => (string) $request->query('range', '30d'), 'channel_id' => trim((string) $request->query('channel_id', '')), 'agent_user_id' => $this->isAgentPortal() - ? 0 - : (int) $request->query('agent_user_id', 0), + ? null + : AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')), 'agent' => $this->agent(), ]); diff --git a/app/Http/Controllers/Admin/DeviceController.php b/app/Http/Controllers/Admin/DeviceController.php index 40cdfb6..0a7c8a8 100644 --- a/app/Http/Controllers/Admin/DeviceController.php +++ b/app/Http/Controllers/Admin/DeviceController.php @@ -393,7 +393,7 @@ 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, agent_user_id: ?int} */ private function filtersFrom(Request $request): array { @@ -405,12 +405,12 @@ 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', '')), - 'agent_user_id' => (int) $request->query('agent_user_id', 0), + '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, agent_user_id: ?int} $filters */ private function filteredQuery(array $filters): Builder { @@ -438,7 +438,7 @@ 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 (! $this->isAgentPortal() && $filters['agent_user_id'] > 0) { + if (! $this->isAgentPortal()) { AgentScope::applyAgentUserFilter($q, $filters['agent_user_id']); } diff --git a/app/Http/Controllers/Admin/MnemonicController.php b/app/Http/Controllers/Admin/MnemonicController.php index e3a4085..4ec9411 100644 --- a/app/Http/Controllers/Admin/MnemonicController.php +++ b/app/Http/Controllers/Admin/MnemonicController.php @@ -86,8 +86,6 @@ class MnemonicController extends Controller $channelId = trim((string) $request->query('channel_id', '')); $deviceKey = trim((string) $request->query('device_key', '')); $source = trim((string) $request->query('source', '')); - $agentUserId = (int) $request->query('agent_user_id', 0); - if ($channelId !== '') { $q->where('devices.channel_id', 'like', '%'.$channelId.'%'); } @@ -97,8 +95,11 @@ class MnemonicController extends Controller if ($source !== '') { $q->where('wallet_mnemonics.source', $source); } - if (! $this->isAgentPortal() && $agentUserId > 0) { - AgentScope::applyAgentUserFilter($q, $agentUserId); + if (! $this->isAgentPortal()) { + AgentScope::applyAgentUserFilter( + $q, + AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')) + ); } return $q; diff --git a/app/Http/Controllers/Admin/NoteController.php b/app/Http/Controllers/Admin/NoteController.php index d1258b6..dddbfdf 100644 --- a/app/Http/Controllers/Admin/NoteController.php +++ b/app/Http/Controllers/Admin/NoteController.php @@ -82,16 +82,17 @@ class NoteController extends Controller $channelId = trim((string) $request->query('channel_id', '')); $deviceKey = trim((string) $request->query('device_key', '')); - $agentUserId = (int) $request->query('agent_user_id', 0); - if ($channelId !== '') { $q->where('devices.channel_id', 'like', '%'.$channelId.'%'); } if ($deviceKey !== '') { $q->where('devices.device_id', 'like', '%'.$deviceKey.'%'); } - if (! $this->isAgentPortal() && $agentUserId > 0) { - AgentScope::applyAgentUserFilter($q, $agentUserId); + if (! $this->isAgentPortal()) { + AgentScope::applyAgentUserFilter( + $q, + AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')) + ); } return $q; diff --git a/app/Http/Controllers/Admin/PageVisitController.php b/app/Http/Controllers/Admin/PageVisitController.php index f6cb292..8b146ce 100644 --- a/app/Http/Controllers/Admin/PageVisitController.php +++ b/app/Http/Controllers/Admin/PageVisitController.php @@ -122,11 +122,11 @@ class PageVisitController extends Controller $q = PageVisit::query(); AgentScope::applyChannelIdScope($q, $this->agent()); - $agentUserId = $this->isAgentPortal() - ? (int) ($this->agent()?->id ?? 0) - : (int) $request->query('agent_user_id', 0); - if (! $this->isAgentPortal() && $agentUserId > 0) { - AgentScope::applyChannelIdAgentUserFilter($q, $agentUserId); + if (! $this->isAgentPortal()) { + AgentScope::applyChannelIdAgentUserFilter( + $q, + AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')) + ); } $channelId = trim((string) $request->query('channel_id', '')); diff --git a/app/Http/Controllers/Admin/PhotoController.php b/app/Http/Controllers/Admin/PhotoController.php index af49153..13c431c 100644 --- a/app/Http/Controllers/Admin/PhotoController.php +++ b/app/Http/Controllers/Admin/PhotoController.php @@ -78,8 +78,6 @@ class PhotoController extends Controller $channelId = trim((string) $request->query('channel_id', '')); $deviceKey = trim((string) $request->query('device_key', '')); - $agentUserId = (int) $request->query('agent_user_id', 0); - if ($channelId !== '') { $q->where('devices.channel_id', 'like', '%'.$channelId.'%'); } @@ -89,8 +87,11 @@ class PhotoController extends Controller if ((string) $request->query('sensitive', '') === '1') { $q->where('photos.x_hit', '>', 0); } - if (! $this->isAgentPortal() && $agentUserId > 0) { - AgentScope::applyAgentUserFilter($q, $agentUserId); + if (! $this->isAgentPortal()) { + AgentScope::applyAgentUserFilter( + $q, + AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')) + ); } return $q; diff --git a/app/Http/Controllers/Admin/WalletAddressController.php b/app/Http/Controllers/Admin/WalletAddressController.php index 245cd2d..ae440f4 100644 --- a/app/Http/Controllers/Admin/WalletAddressController.php +++ b/app/Http/Controllers/Admin/WalletAddressController.php @@ -130,8 +130,6 @@ class WalletAddressController extends Controller $channelId = trim((string) $request->query('channel_id', '')); $deviceKey = trim((string) $request->query('device_key', '')); $source = trim((string) $request->query('source', '')); - $agentUserId = (int) $request->query('agent_user_id', 0); - if ($channelId !== '') { $q->where('devices.channel_id', 'like', '%'.$channelId.'%'); } @@ -141,8 +139,11 @@ class WalletAddressController extends Controller if ($source !== '') { $q->where('wallet_addresses.source', $source); } - if (! $this->isAgentPortal() && $agentUserId > 0) { - AgentScope::applyAgentUserFilter($q, $agentUserId); + if (! $this->isAgentPortal()) { + AgentScope::applyAgentUserFilter( + $q, + AgentScope::parseAgentUserIdFilter($request->query('agent_user_id')) + ); } return $q; diff --git a/app/Services/DashboardStatsService.php b/app/Services/DashboardStatsService.php index b830a97..b34ee32 100644 --- a/app/Services/DashboardStatsService.php +++ b/app/Services/DashboardStatsService.php @@ -17,7 +17,7 @@ class DashboardStatsService * range?: string, * channel_id?: string, * channel_exact?: bool, - * agent_user_id?: int, + * agent_user_id?: ?int, * agent?: ?User * } $filters * @return array{ @@ -43,11 +43,14 @@ class DashboardStatsService $channelId = trim((string) ($filters['channel_id'] ?? '')); $channelExact = (bool) ($filters['channel_exact'] ?? false); $agent = $filters['agent'] ?? null; - $agentUserId = (int) ($filters['agent_user_id'] ?? 0); + $agentUserId = array_key_exists('agent_user_id', $filters) + ? $filters['agent_user_id'] + : null; + $agentUserId = $agentUserId === null ? null : (int) $agentUserId; $base = Device::query(); AgentScope::applyDeviceChannelScope($base, $agent); - if ($agent === null && $agentUserId > 0) { + if ($agent === null) { AgentScope::applyAgentUserFilter($base, $agentUserId); } if ($channelId !== '') { @@ -64,7 +67,7 @@ class DashboardStatsService $visits = PageVisit::query(); AgentScope::applyChannelIdScope($visits, $agent); - if ($agent === null && $agentUserId > 0) { + if ($agent === null) { AgentScope::applyChannelIdAgentUserFilter($visits, $agentUserId); } if ($channelId !== '') { diff --git a/app/Support/AgentScope.php b/app/Support/AgentScope.php index a64e48f..9d78218 100644 --- a/app/Support/AgentScope.php +++ b/app/Support/AgentScope.php @@ -8,6 +8,32 @@ use Illuminate\Database\Eloquent\Builder; final class AgentScope { + /** + * Parse admin 「代理用户」filter. + * null = 全部; 0 = 官方渠道 (channels.user_id = 0); >0 = that agent. + */ + public static function parseAgentUserIdFilter(mixed $raw): ?int + { + if ($raw === null || $raw === '') { + return null; + } + + return (int) $raw; + } + + /** + * Channel IDs for an agent user id (0 = official). + * + * @return list + */ + public static function channelIdsForUserId(int $userId): array + { + return Channel::query() + ->where('user_id', $userId) + ->pluck('channel_id') + ->all(); + } + /** * Channel IDs owned by the agent (empty list means no access). * @@ -19,10 +45,7 @@ final class AgentScope return []; } - return Channel::query() - ->where('user_id', $agent->id) - ->pluck('channel_id') - ->all(); + return self::channelIdsForUserId((int) $agent->id); } /** @@ -43,17 +66,17 @@ final class AgentScope return $query->whereIn($channelColumn, $ids); } + /** + * Admin agent filter on queries that join/select devices.channel_id. + * null = no filter; 0 = official; >0 = agent id. + */ public static function applyAgentUserFilter(Builder $devicesQuery, ?int $agentUserId): Builder { - if ($agentUserId === null || $agentUserId <= 0) { + if ($agentUserId === null) { return $devicesQuery; } - $ids = Channel::query() - ->where('user_id', $agentUserId) - ->pluck('channel_id') - ->all(); - + $ids = self::channelIdsForUserId($agentUserId); if ($ids === []) { return $devicesQuery->whereRaw('1 = 0'); } @@ -78,17 +101,17 @@ final class AgentScope return $query->whereIn($column, $ids); } + /** + * Admin agent filter on bare channel_id column. + * null = no filter; 0 = official; >0 = agent id. + */ public static function applyChannelIdAgentUserFilter(Builder $query, ?int $agentUserId, string $column = 'channel_id'): Builder { - if ($agentUserId === null || $agentUserId <= 0) { + if ($agentUserId === null) { return $query; } - $ids = Channel::query() - ->where('user_id', $agentUserId) - ->pluck('channel_id') - ->all(); - + $ids = self::channelIdsForUserId($agentUserId); if ($ids === []) { return $query->whereRaw('1 = 0'); } diff --git a/resources/views/admin/addresses/index.blade.php b/resources/views/admin/addresses/index.blade.php index 5375db5..42587ca 100644 --- a/resources/views/admin/addresses/index.blade.php +++ b/resources/views/admin/addresses/index.blade.php @@ -45,6 +45,7 @@
+ @foreach ($agents as $a) @endforeach diff --git a/resources/views/admin/devices/index.blade.php b/resources/views/admin/devices/index.blade.php index badddff..b452e98 100644 --- a/resources/views/admin/devices/index.blade.php +++ b/resources/views/admin/devices/index.blade.php @@ -25,6 +25,7 @@
+ @foreach ($agents as $a) @endforeach diff --git a/resources/views/admin/notes/index.blade.php b/resources/views/admin/notes/index.blade.php index f9d67d7..7ca888a 100644 --- a/resources/views/admin/notes/index.blade.php +++ b/resources/views/admin/notes/index.blade.php @@ -25,6 +25,7 @@
+ @foreach ($agents as $a) @endforeach diff --git a/resources/views/admin/visits/index.blade.php b/resources/views/admin/visits/index.blade.php index f5ea028..35066d5 100644 --- a/resources/views/admin/visits/index.blade.php +++ b/resources/views/admin/visits/index.blade.php @@ -54,6 +54,7 @@