Main #7

Merged
dsutanto merged 7 commits from dsutanto/Deep-Package-Inspection:main into Proxy_Server_API_Netify 2026-07-17 13:59:59 +07:00
6 changed files with 45 additions and 11280 deletions

No files matched your search

+31
View File
@@ -0,0 +1,31 @@
FROM oven/bun:1-alpine AS base
FROM base AS deps
WORKDIR /app
COPY package.json .
RUN bun install
FROM base AS builder
WORKDIR /app
ARG NEXT_PUBLIC_API_URL=http://127.0.0.1:3001
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN bun run build
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
ENV PORT 3000
ENV HOSTNAME "0.0.0.0"
CMD ["bun", "run", "server.js"]
+10 -6
View File
@@ -44,21 +44,25 @@ async function populateAppCache(BASE_URL, token, siteUuid) {
const headers = { 'x-api-key': token, 'Accept': 'application/json' }; const headers = { 'x-api-key': token, 'Accept': 'application/json' };
if (siteUuid) headers['x-net-site'] = siteUuid; if (siteUuid) headers['x-net-site'] = siteUuid;
const res = await axios.get(`${BASE_URL}/lookup/applications`, { const res = await axios.get(`${BASE_URL}/lookup/applications`, {
headers, params: { settings_limit: 2000 }, timeout: 8000 headers, params: { settings_limit: 5000 }, timeout: 20000
}); });
appLookupCache = {}; appLookupCache = {};
if (res.data && Array.isArray(res.data.data)) { if (res.data && Array.isArray(res.data.data)) {
res.data.data.forEach(a => { res.data.data.forEach(a => {
if (!a.label || !a.id) return; if (!a.id) return;
const label = (a.label || '').trim();
if (!label) return;
let domain = null; let domain = null;
if (a.home_page?.url) { if (a.home_page?.url) {
domain = a.home_page.url.replace(/^https?:\/\/(www\.)?/, '').split('/')[0]; domain = a.home_page.url.replace(/^https?:\/\/(www\.)?/, '').split('/')[0];
} else if (a.domain_list?.length > 0) { } else if (a.domain_list?.length > 0) {
domain = a.domain_list[0].label; domain = a.domain_list[0].label;
} else { } else {
domain = a.label.toLowerCase(); domain = label.toLowerCase();
} }
appLookupCache[a.label.toLowerCase()] = { id: a.id, label: a.label, domain }; const entry = { id: a.id, label, domain };
appLookupCache[label.toLowerCase()] = entry;
if (a.tag) appLookupCache[a.tag.toLowerCase()] = entry;
}); });
} }
console.log(`[AppDetailsDpiHelper] App cache: ${Object.keys(appLookupCache).length} apps`); console.log(`[AppDetailsDpiHelper] App cache: ${Object.keys(appLookupCache).length} apps`);
@@ -92,12 +96,12 @@ async function fetchFromDpiApi(label, agentUuid, timeRange, token, siteUuid) {
const params = { const params = {
filter_interval: timeRangeToMinutes(timeRange), filter_interval: timeRangeToMinutes(timeRange),
filter_applications: `["${appInfo.id}"]`, filter_applications: `[${appInfo.id}]`,
settings_limit: 10000 settings_limit: 10000
}; };
if (agentUuid && agentMapCache?.[agentUuid]) { if (agentUuid && agentMapCache?.[agentUuid]) {
params.filter_agents = `[${agentMapCache[agentUuid]}]`; params.filter_agents = `["${agentMapCache[agentUuid]}"]`;
} }
const [dlRes, ulRes] = await Promise.all([ const [dlRes, ulRes] = await Promise.all([
+2 -2
View File
@@ -40,7 +40,7 @@ module.exports = async function appDetailsHandler(req, res, helpers) {
if (deviceApps.length > 0) { if (deviceApps.length > 0) {
// Pre-load application lookup to resolve default domains // Pre-load application lookup to resolve default domains
const BASE_URL = process.env.NETIFY_INFORMATICS_BASE_URL || 'https://informatics.netify.ai/api/v1'; const BASE_URL = process.env.NETIFY_INFORMATICS_BASE_URL || 'https://informatics.netify.ai/api/v1';
if (token && SITE_UUID) { if (token) {
await populateAppCache(BASE_URL, token, SITE_UUID).catch(e => console.warn('[AppDetails] Cache error:', e.message)); await populateAppCache(BASE_URL, token, SITE_UUID).catch(e => console.warn('[AppDetails] Cache error:', e.message));
} }
const appMeta = getAppLookupCache()?.[label.toLowerCase()]; const appMeta = getAppLookupCache()?.[label.toLowerCase()];
@@ -96,7 +96,7 @@ module.exports = async function appDetailsHandler(req, res, helpers) {
} }
// ── Step 2: Fall back to DPI API only if MongoDB has ZERO data ──────────── // ── Step 2: Fall back to DPI API only if MongoDB has ZERO data ────────────
if (token && SITE_UUID) { if (token) {
const dpiResult = await fetchFromDpiApi(label, agentUuid, req.query.timeRange, token, SITE_UUID); const dpiResult = await fetchFromDpiApi(label, agentUuid, req.query.timeRange, token, SITE_UUID);
if (dpiResult) { if (dpiResult) {
console.log(`[AppDetails] DPI fallback: label=${label} time=${Date.now()-t0}ms`); console.log(`[AppDetails] DPI fallback: label=${label} time=${Date.now()-t0}ms`);
+2 -7
View File
@@ -6,7 +6,7 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
output: "standalone", output: "standalone",
serverExternalPackages: ["mongoose", "better-sqlite3"], serverExternalPackages: ["mongoose"],
experimental: { experimental: {
serverActions: { serverActions: {
allowedOrigins: [ allowedOrigins: [
@@ -46,12 +46,7 @@ const nextConfig: NextConfig = {
], ],
}, },
async rewrites() { async rewrites() {
return [ return [];
{
source: '/api/:path*',
destination: `${process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:3001'}/api/:path*`,
},
];
}, },
}; };
-11264
View File
File diff suppressed because it is too large. Load diff
-1
View File
@@ -27,7 +27,6 @@
"@types/leaflet": "^1.9.21", "@types/leaflet": "^1.9.21",
"axios": "^1.18.1", "axios": "^1.18.1",
"bcryptjs": "^3.0.3", "bcryptjs": "^3.0.3",
"better-sqlite3": "^12.11.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"concurrently": "^10.0.3", "concurrently": "^10.0.3",
"cookie": "^2.0.1", "cookie": "^2.0.1",