v1.1: Add CIDR subnet filtering and Agent filter in Devices page

This commit is contained in:
ypratama committed 2026-08-27 12:02:01 +07:00
commit 966058e2fe
422 files changed
+54656

No files matched your search

+132
View File
@@ -0,0 +1,132 @@
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const Session = require('../models/Session');
const { Summary } = require('../models/Schemas');
const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-backone-key';
async function requireAuth(req, res, next) {
const token = req.cookies?.token;
if (!token) return res.status(401).json({ error: 'Unauthorized' });
try {
req.user = jwt.verify(token, JWT_SECRET);
// Verify session status in MongoDB
if (req.user.session_id) {
const activeSession = await Session.findById(req.user.session_id);
if (!activeSession) {
res.clearCookie('token');
return res.status(401).json({ error: 'Sesi login telah dinonaktifkan atau kedaluwarsa.' });
}
// Debounce last_active update: only update if older than 60s, and execute asynchronously
const now = new Date();
if (!activeSession.last_active || (now.getTime() - new Date(activeSession.last_active).getTime() > 60000)) {
activeSession.last_active = now;
activeSession.save().catch(err => console.error('[Auth] Session save err:', err.message));
}
}
// ── VIEW-AS MODE ──────────────────────────────────────────────────────────
const viewAsHeader = req.headers['x-view-as-agent'];
const isAllowedViewAs = req.user.role === 'SUPER_ADMIN' ||
req.user.role === 'TENANT_ADMIN' ||
req.user.role === 'COMPANY_ADMIN' ||
req.user.role === 'COMPANY_OPERATOR';
if (viewAsHeader && isAllowedViewAs) {
try {
const viewDecoded = jwt.verify(viewAsHeader, JWT_SECRET);
if (viewDecoded.type === 'view-as' && viewDecoded.adminId === req.user.id && viewDecoded.viewAs) {
const targetAgent = viewDecoded.viewAs;
// Validation: COMPANY_ADMIN and COMPANY_OPERATOR can only view-as their assigned agents
if (['COMPANY_ADMIN', 'COMPANY_OPERATOR'].includes(req.user.role)) {
const hasAccess = req.user.agent_uuids && req.user.agent_uuids.includes(targetAgent);
if (!hasAccess) {
throw new Error('Unauthorized view-as agent access');
}
}
let targetUserDoc = null;
if (viewDecoded.target_user_id) {
targetUserDoc = await User.findById(viewDecoded.target_user_id).lean();
} else if (viewDecoded.target_username) {
targetUserDoc = await User.findOne({ username: viewDecoded.target_username }).lean();
} else {
targetUserDoc = await User.findOne({ agent_uuid: targetAgent, role: 'AGENT_VIEWER' }).lean();
}
let targetSiteUuid = req.user.site_uuid;
if (targetUserDoc && targetUserDoc.site_uuid) {
targetSiteUuid = targetUserDoc.site_uuid;
} else {
const summaryDoc = await Summary.findOne({ agent_uuid: targetAgent }).lean();
if (summaryDoc && summaryDoc.site_uuid) {
targetSiteUuid = summaryDoc.site_uuid;
}
}
req.user = {
...req.user,
role: targetUserDoc ? targetUserDoc.role : 'AGENT_VIEWER',
agent_uuid: targetUserDoc ? (targetUserDoc.agent_uuid || targetAgent) : targetAgent,
agent_uuids: targetUserDoc ? (targetUserDoc.agent_uuids || [targetAgent]) : [targetAgent],
agent_label: viewDecoded.viewAsLabel,
site_uuid: targetSiteUuid,
company_name: targetUserDoc ? targetUserDoc.company_name : req.user.company_name,
_viewAsMode: true,
_viewAsUser: !!targetUserDoc,
_targetUserId: targetUserDoc ? targetUserDoc.id : null,
_originalRole: req.user.role,
};
}
} catch (viewErr) {
console.warn('[ViewAs] Invalid view-as token, ignoring:', viewErr.message);
}
}
next();
} catch (err) {
res.clearCookie('token');
res.status(401).json({ error: 'Invalid token' });
}
}
async function requireAdmin(req, res, next) {
const token = req.cookies?.token;
if (!token) return res.status(401).json({ error: 'Not authenticated' });
try {
const decoded = jwt.verify(token, JWT_SECRET);
// Verify session status in MongoDB
if (decoded.session_id) {
const activeSession = await Session.findById(decoded.session_id);
if (!activeSession) {
res.clearCookie('token');
return res.status(401).json({ error: 'Sesi login telah dinonaktifkan atau kedaluwarsa.' });
}
const now = new Date();
if (!activeSession.last_active || (now.getTime() - new Date(activeSession.last_active).getTime() > 60000)) {
activeSession.last_active = now;
activeSession.save().catch(err => console.error('[AuthAdmin] Session save err:', err.message));
}
}
const validAdminRoles = ['SUPER_ADMIN', 'COMPANY_ADMIN', 'COMPANY_OPERATOR', 'TENANT_ADMIN', 'SOC_ANALYST'];
if (!validAdminRoles.includes(decoded.role)) {
return res.status(403).json({ error: 'Forbidden' });
}
req.adminUser = decoded;
next();
} catch {
res.clearCookie('token');
res.status(401).json({ error: 'Token tidak valid' });
}
}
module.exports = {
requireAuth,
requireAdmin,
JWT_SECRET
};