130 lines
4.6 KiB
JavaScript
130 lines
4.6 KiB
JavaScript
const { CustomDeviceLabel, Flow } = require('../../models/Schemas');
|
|
|
|
// Valid tenant site UUIDs (from env). A global user requesting a site that is not
|
|
// in this list (e.g. a stale 'test-site' from the account's site_uuid column) must
|
|
// NOT silently filter everything out — treat it as "all sites" instead.
|
|
const KNOWN_SITES = (process.env.BACKONE_SITE_UUIDS || process.env.BACKONE_SITE_UUID || '')
|
|
.split(',')
|
|
.map(s => s.trim())
|
|
.filter(Boolean);
|
|
|
|
function isKnownSite(siteUuid) {
|
|
// Empty env => no known-site list configured, keep legacy behavior (filter anything).
|
|
return KNOWN_SITES.length === 0 || KNOWN_SITES.includes(siteUuid);
|
|
}
|
|
|
|
function getTimeFilter(req) {
|
|
// Explicit calendar date range (from the per-page date picker) takes priority
|
|
// over the global sidebar time range. Both dates are interpreted as WIB (UTC+7)
|
|
// to match the dashboard's display timezone (Rule 20).
|
|
const dateFrom = req.query.date_from;
|
|
const dateTo = req.query.date_to;
|
|
if (dateFrom || dateTo) {
|
|
const filter = {};
|
|
if (dateFrom) filter.$gte = new Date(`${dateFrom}T00:00:00.000+07:00`);
|
|
if (dateTo) filter.$lte = new Date(`${dateTo}T23:59:59.999+07:00`);
|
|
return filter;
|
|
}
|
|
|
|
// Fall back to sidebar global time range
|
|
const range = req.query.timeRange || '1d';
|
|
if (range === 'all') return null;
|
|
const now = new Date();
|
|
const ms = {
|
|
'5m': 5 * 60000,
|
|
'30m': 30 * 60000,
|
|
'1h': 1 * 3600000,
|
|
'1d': 24 * 3600000,
|
|
'7d': 7 * 24 * 3600000,
|
|
'30d': 30 * 24 * 3600000,
|
|
};
|
|
const delta = ms[range] ?? ms['1d'];
|
|
return { $gte: new Date(now.getTime() - delta) };
|
|
}
|
|
|
|
|
|
function getBaseFilter(req, timeFilter = null) {
|
|
const filter = {};
|
|
if (timeFilter) filter.timestamp = timeFilter;
|
|
|
|
const requestedSiteUuid = req.headers['x-backone-site-uuid'];
|
|
|
|
const isGlobalUser = req.user?.role === 'SUPER_ADMIN' ||
|
|
req.user?.role === 'EXECUTIVE' ||
|
|
((!req.user?.site_uuid || req.user?.site_uuid === 'default') && ['SOC_ANALYST', 'ENGINEER'].includes(req.user?.role));
|
|
|
|
if (isGlobalUser && requestedSiteUuid && requestedSiteUuid !== 'all' && isKnownSite(requestedSiteUuid)) {
|
|
filter.site_uuid = { $in: [requestedSiteUuid, 'global'] };
|
|
} else if (isGlobalUser && KNOWN_SITES.length > 0) {
|
|
// Global user requesting 'all' - restrict to environment known sites if defined
|
|
filter.site_uuid = { $in: [...KNOWN_SITES, 'global'] };
|
|
} else if (!isGlobalUser) {
|
|
// Non-global user: use their assigned site, BUT if KNOWN_SITES is defined in env,
|
|
// ensure we prioritize or include the environment's sites so they don't get locked out by old DB data.
|
|
const userSite = req.user?.site_uuid;
|
|
if (KNOWN_SITES.length > 0) {
|
|
filter.site_uuid = { $in: [...KNOWN_SITES, userSite, 'global'].filter(Boolean) };
|
|
} else if (userSite) {
|
|
filter.site_uuid = { $in: [userSite, 'global'] };
|
|
}
|
|
}
|
|
|
|
// Restrict agent based on role and explicit query
|
|
if (req.user?.role && ['COMPANY_ADMIN', 'COMPANY_OPERATOR', 'COMPANY_VIEWER'].includes(req.user.role)) {
|
|
if (req.query?.agent_uuid && (req.user.agent_uuids || []).includes(req.query.agent_uuid)) {
|
|
filter.agent_uuid = req.query.agent_uuid;
|
|
} else {
|
|
filter.agent_uuid = { $in: req.user.agent_uuids || [] };
|
|
}
|
|
} else if (req.user?.role === 'AGENT_VIEWER' && req.user?.agent_uuid) {
|
|
// AGENT_VIEWER is strictly limited to their own agent
|
|
filter.agent_uuid = req.user.agent_uuid;
|
|
} else if (req.query?.agent_uuid) {
|
|
// SUPER_ADMIN and other global roles can query any agent
|
|
filter.agent_uuid = req.query.agent_uuid;
|
|
}
|
|
|
|
console.log('[DEBUG getBaseFilter]', { headers: req.headers, filter });
|
|
return filter;
|
|
}
|
|
|
|
async function getCustomLabelsMap() {
|
|
try {
|
|
const list = await CustomDeviceLabel.find().lean();
|
|
const map = {};
|
|
list.forEach(c => {
|
|
map[c.mac_address] = c.device_label;
|
|
});
|
|
return map;
|
|
} catch (err) {
|
|
console.error('[getCustomLabelsMap] failed:', err.message);
|
|
return {};
|
|
}
|
|
}
|
|
|
|
async function topFlowField(fieldName, req, limit = 20) {
|
|
const timeFilter = getTimeFilter(req);
|
|
const matchBase = getBaseFilter(req, timeFilter);
|
|
|
|
return Flow.aggregate([
|
|
{ $match: { ...matchBase, [fieldName]: { $ne: null, $ne: '' } } },
|
|
{ $group: {
|
|
_id: `$${fieldName}`,
|
|
download: { $sum: '$download' },
|
|
upload: { $sum: '$upload' },
|
|
count: { $sum: 1 },
|
|
}},
|
|
{ $project: { label: '$_id', download: 1, upload: 1, count: 1, _id: 0 } },
|
|
{ $sort: { download: -1 } },
|
|
{ $limit: limit },
|
|
]);
|
|
}
|
|
|
|
module.exports = {
|
|
getTimeFilter,
|
|
getBaseFilter,
|
|
getCustomLabelsMap,
|
|
topFlowField,
|
|
isKnownSite
|
|
};
|