api->request('GET', '/api/v1/admin/me', [], $actingUserId); return UserDto::fromArray($payload); } // ---- IPs / dashboard (M09) ---- /** * @param array $filters */ public function searchIps(int $actingUserId, array $filters, int $page = 1, int $pageSize = 25): IpListDto { $query = ['page' => $page, 'page_size' => $pageSize]; foreach (['q', 'category', 'min_score', 'max_score', 'country', 'asn', 'status'] as $key) { if (isset($filters[$key]) && $filters[$key] !== '' && $filters[$key] !== null) { $query[$key] = $filters[$key]; } } $payload = $this->api->request('GET', '/api/v1/admin/ips', ['query' => $query], $actingUserId); return IpListDto::fromArray($payload); } public function getIp(int $actingUserId, string $ip): IpDetailDto { $payload = $this->api->request('GET', '/api/v1/admin/ips/' . rawurlencode($ip), [], $actingUserId); return IpDetailDto::fromArray($payload); } public function getDashboardStats(int $actingUserId): DashboardStatsDto { $payload = $this->api->request('GET', '/api/v1/admin/stats/dashboard', [], $actingUserId); return DashboardStatsDto::fromArray($payload); } /** * @return list */ public function listCountries(int $actingUserId): array { $payload = $this->api->request('GET', '/api/v1/admin/ips/countries', [], $actingUserId); $items = $payload['items'] ?? []; if (!is_array($items)) { return []; } $out = []; foreach ($items as $item) { if (!is_array($item)) { continue; } $out[] = [ 'code' => (string) ($item['code'] ?? ''), 'count' => (int) ($item['count'] ?? 0), ]; } return $out; } // ---- manual blocks (M10) ---- /** * @return array */ public function listManualBlocks(int $actingUserId, ?string $kind = null): array { $query = ['limit' => 200]; if ($kind !== null && $kind !== '') { $query['kind'] = $kind; } return $this->api->request('GET', '/api/v1/admin/manual-blocks', ['query' => $query], $actingUserId); } /** * @param array $body * @return array */ public function createManualBlock(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/manual-blocks', ['json' => $body], $actingUserId); } public function deleteManualBlock(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/manual-blocks/' . $id, [], $actingUserId); } // ---- allowlist (M10) ---- /** * @return array */ public function listAllowlist(int $actingUserId, ?string $kind = null): array { $query = ['limit' => 200]; if ($kind !== null && $kind !== '') { $query['kind'] = $kind; } return $this->api->request('GET', '/api/v1/admin/allowlist', ['query' => $query], $actingUserId); } /** * @param array $body * @return array */ public function createAllowlist(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/allowlist', ['json' => $body], $actingUserId); } public function deleteAllowlist(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/allowlist/' . $id, [], $actingUserId); } // ---- policies (M10) ---- /** * @return array */ public function listPolicies(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/policies', [], $actingUserId); } /** * @return array */ public function getPolicy(int $actingUserId, int $id): array { return $this->api->request('GET', '/api/v1/admin/policies/' . $id, [], $actingUserId); } /** * @param array $body * @return array */ public function createPolicy(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/policies', ['json' => $body], $actingUserId); } /** * @param array $body * @return array */ public function updatePolicy(int $actingUserId, int $id, array $body): array { return $this->api->request('PATCH', '/api/v1/admin/policies/' . $id, ['json' => $body], $actingUserId); } public function deletePolicy(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/policies/' . $id, [], $actingUserId); } /** * @return array */ public function previewPolicy(int $actingUserId, int $id): array { return $this->api->request('GET', '/api/v1/admin/policies/' . $id . '/preview', [], $actingUserId); } // ---- reporters (M10) ---- /** * @return array */ public function listReporters(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/reporters', ['query' => ['limit' => 200]], $actingUserId); } /** * @return array */ public function getReporter(int $actingUserId, int $id): array { return $this->api->request('GET', '/api/v1/admin/reporters/' . $id, [], $actingUserId); } /** * @param array $body * @return array */ public function createReporter(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/reporters', ['json' => $body], $actingUserId); } /** * @param array $body * @return array */ public function updateReporter(int $actingUserId, int $id, array $body): array { return $this->api->request('PATCH', '/api/v1/admin/reporters/' . $id, ['json' => $body], $actingUserId); } public function deleteReporter(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/reporters/' . $id, [], $actingUserId); } // ---- consumers (M10) ---- /** * @return array */ public function listConsumers(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/consumers', ['query' => ['limit' => 200]], $actingUserId); } /** * @return array */ public function getConsumer(int $actingUserId, int $id): array { return $this->api->request('GET', '/api/v1/admin/consumers/' . $id, [], $actingUserId); } /** * @param array $body * @return array */ public function createConsumer(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/consumers', ['json' => $body], $actingUserId); } /** * @param array $body * @return array */ public function updateConsumer(int $actingUserId, int $id, array $body): array { return $this->api->request('PATCH', '/api/v1/admin/consumers/' . $id, ['json' => $body], $actingUserId); } public function deleteConsumer(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/consumers/' . $id, [], $actingUserId); } // ---- tokens (M10) ---- /** * @return array */ public function listTokens(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/tokens', ['query' => ['limit' => 200]], $actingUserId); } /** * @param array $body * @return array */ public function createToken(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/tokens', ['json' => $body], $actingUserId); } public function deleteToken(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/tokens/' . $id, [], $actingUserId); } // ---- categories (M10) ---- /** * @return array */ public function listCategories(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/categories', [], $actingUserId); } /** * @return array */ public function getCategory(int $actingUserId, int $id): array { return $this->api->request('GET', '/api/v1/admin/categories/' . $id, [], $actingUserId); } /** * @param array $body * @return array */ public function createCategory(int $actingUserId, array $body): array { return $this->api->request('POST', '/api/v1/admin/categories', ['json' => $body], $actingUserId); } /** * @param array $body * @return array */ public function updateCategory(int $actingUserId, int $id, array $body): array { return $this->api->request('PATCH', '/api/v1/admin/categories/' . $id, ['json' => $body], $actingUserId); } public function deleteCategory(int $actingUserId, int $id): void { $this->api->request('DELETE', '/api/v1/admin/categories/' . $id, [], $actingUserId); } // ---- audit / settings (M12) ---- /** * @param array $filters * @return array */ public function listAuditLog(int $actingUserId, array $filters, int $page = 1, int $pageSize = 50): array { $query = ['page' => $page, 'page_size' => $pageSize]; foreach (['actor_kind', 'actor_id', 'action', 'entity_type', 'entity_id', 'from', 'to'] as $key) { if (isset($filters[$key]) && $filters[$key] !== '' && $filters[$key] !== null) { $query[$key] = $filters[$key]; } } return $this->api->request('GET', '/api/v1/admin/audit-log', ['query' => $query], $actingUserId); } /** * @return array */ public function getJobsStatus(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/jobs/status', [], $actingUserId); } /** * @param array $params * @return array */ public function triggerJob(int $actingUserId, string $name, array $params = []): array { return $this->api->request( 'POST', '/api/v1/admin/jobs/trigger/' . rawurlencode($name), $params === [] ? [] : ['json' => $params], $actingUserId, ); } /** * @return array */ public function getConfig(int $actingUserId): array { return $this->api->request('GET', '/api/v1/admin/config', [], $actingUserId); } /** * Wipe operational data on the api side. The API requires * `confirm: "PURGE"` in the body — anything else returns 400. * * @return array */ public function purgeData(int $actingUserId): array { return $this->api->request( 'POST', '/api/v1/admin/maintenance/purge', ['json' => ['confirm' => 'PURGE']], $actingUserId, ); } /** * Load the demo dataset. Returns 409 if data is already seeded. * * @return array */ public function seedDemo(int $actingUserId): array { return $this->api->request( 'POST', '/api/v1/admin/maintenance/seed-demo', [], $actingUserId, ); } }