feat(api): enhance IP list management with new entry operations and improved error handling
- Added endpoints for adding and deleting entries in IP lists. - Refactored list creation logic to handle manual list types more effectively. - Updated refresh logic to rebuild manual list entries. - Improved error handling for entry operations to ensure data integrity. - Enhanced response structure for list detail retrieval. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { createHash } from 'node:crypto'
|
||||
import { resolve4, resolve6 } from 'node:dns/promises'
|
||||
import type { Db } from '@evofw/db'
|
||||
import { repos } from '@evofw/db'
|
||||
import { refreshAllHostnameRules } from '../policy/resolve-hostname.js'
|
||||
import { rebuildManualListEntries } from './entries.js'
|
||||
|
||||
function uniq(cidrs: string[]): string[] {
|
||||
return [...new Set(cidrs.map((c) => c.trim()).filter(Boolean))].sort()
|
||||
@@ -46,27 +47,6 @@ async function fetchJsonUrl(url: string): Promise<string[]> {
|
||||
return uniq(out)
|
||||
}
|
||||
|
||||
async function resolveDomains(domains: string[]): Promise<string[]> {
|
||||
const out: string[] = []
|
||||
for (const d of domains) {
|
||||
const host = d.trim().replace(/\.$/, '')
|
||||
if (!host) continue
|
||||
try {
|
||||
const a = await resolve4(host)
|
||||
out.push(...a.map((ip) => `${ip}/32`))
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
try {
|
||||
const aaaa = await resolve6(host)
|
||||
out.push(...aaaa.map((ip) => `${ip}/128`))
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
return uniq(out)
|
||||
}
|
||||
|
||||
async function fetchEvobgpCommunity(
|
||||
apiUrl: string,
|
||||
token: string,
|
||||
@@ -118,21 +98,13 @@ export async function refreshIpList(db: Db, listId: string): Promise<void> {
|
||||
|
||||
try {
|
||||
let cidrs: string[] = []
|
||||
if (list.type === 'static') {
|
||||
cidrs = repos.listIpListEntries(db, listId).map((e) => e.cidr)
|
||||
if (list.type === 'static' || list.type === 'domains') {
|
||||
cidrs = await rebuildManualListEntries(db, listId)
|
||||
} else if (list.type === 'json_url') {
|
||||
const url = String(config.url ?? '')
|
||||
if (!url) throw new Error('config.url required')
|
||||
cidrs = await fetchJsonUrl(url)
|
||||
repos.replaceIpListEntries(db, listId, cidrs)
|
||||
} else if (list.type === 'domains') {
|
||||
const domains = Array.isArray(config.domains)
|
||||
? (config.domains as string[])
|
||||
: String(config.domains ?? '')
|
||||
.split(/[\s,]+/)
|
||||
.filter(Boolean)
|
||||
cidrs = await resolveDomains(domains)
|
||||
repos.replaceIpListEntries(db, listId, cidrs)
|
||||
} else if (list.type === 'evobgp_community') {
|
||||
const apiUrl =
|
||||
String(config.api_url ?? '') || repos.getSetting(db, 'evobgp_api_url')
|
||||
@@ -154,10 +126,7 @@ export async function refreshIpList(db: Db, listId: string): Promise<void> {
|
||||
lastError: null,
|
||||
})
|
||||
|
||||
// Bump all agents so they re-fetch policy
|
||||
for (const a of repos.listAgents(db)) {
|
||||
if (a.status === 'approved') repos.bumpAgentGeneration(db, a.id)
|
||||
}
|
||||
repos.bumpAgentsForList(db, listId)
|
||||
} catch (err) {
|
||||
repos.updateIpList(db, listId, {
|
||||
lastError: err instanceof Error ? err.message : String(err),
|
||||
@@ -166,11 +135,8 @@ export async function refreshIpList(db: Db, listId: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
import { refreshAllHostnameRules } from '../policy/resolve-hostname.js'
|
||||
|
||||
export async function refreshAllLists(db: Db): Promise<void> {
|
||||
for (const list of repos.listIpLists(db)) {
|
||||
if (list.type === 'static') continue
|
||||
await refreshIpList(db, list.id)
|
||||
}
|
||||
await refreshAllHostnameRules(db)
|
||||
|
||||
Reference in New Issue
Block a user