feat(source2): push all latest files - device labeling, help system, proxy docs, database isolation fix
- Added DOKUMENTASI-FILTER-PER-SITE.md (site isolation docs) - Fixed start-with-env.js to force-load .env.production - Fixed MONGODB_URI hostname from mongodb-netify to mongodb.prod.proit.id - Updated .gitignore to exclude sensitive scripts and credential files - Minor UI and labeling improvements
This commit is contained in:
1 parent
a403f752f3
commit
dd4c8f6876
385 files changed
+31016
-8268
No files matched your search
@@ -1,5 +1,6 @@
|
||||
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';
|
||||
@@ -11,19 +12,46 @@ async function requireAuth(req, res, next) {
|
||||
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.' });
|
||||
}
|
||||
// Update last active
|
||||
activeSession.last_active = new Date();
|
||||
await activeSession.save();
|
||||
}
|
||||
|
||||
// ── VIEW-AS MODE ──────────────────────────────────────────────────────────
|
||||
const viewAsHeader = req.headers['x-view-as-agent'];
|
||||
if (viewAsHeader && (req.user.role === 'SUPER_ADMIN' || req.user.role === 'TENANT_ADMIN')) {
|
||||
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 targetAgentUser = await User.findOne({ agent_uuid: viewDecoded.viewAs, role: 'AGENT_VIEWER' }).lean();
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
const targetAgentUser = await User.findOne({ agent_uuid: targetAgent, role: 'AGENT_VIEWER' }).lean();
|
||||
|
||||
let targetSiteUuid = req.user.site_uuid;
|
||||
if (targetAgentUser && targetAgentUser.site_uuid) {
|
||||
targetSiteUuid = targetAgentUser.site_uuid;
|
||||
} else {
|
||||
const summaryDoc = await Summary.findOne({ agent_uuid: viewDecoded.viewAs }).lean();
|
||||
const summaryDoc = await Summary.findOne({ agent_uuid: targetAgent }).lean();
|
||||
if (summaryDoc && summaryDoc.site_uuid) {
|
||||
targetSiteUuid = summaryDoc.site_uuid;
|
||||
}
|
||||
@@ -32,7 +60,7 @@ async function requireAuth(req, res, next) {
|
||||
req.user = {
|
||||
...req.user,
|
||||
role: 'AGENT_VIEWER',
|
||||
agent_uuid: viewDecoded.viewAs,
|
||||
agent_uuid: targetAgent,
|
||||
agent_label: viewDecoded.viewAsLabel,
|
||||
site_uuid: targetSiteUuid,
|
||||
_viewAsMode: true,
|
||||
@@ -50,12 +78,25 @@ async function requireAuth(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
function requireAdmin(req, res, next) {
|
||||
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);
|
||||
if (decoded.role !== 'SUPER_ADMIN' && decoded.role !== 'TENANT_ADMIN' && decoded.role !== 'SOC_ANALYST') {
|
||||
|
||||
// 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.' });
|
||||
}
|
||||
activeSession.last_active = new Date();
|
||||
await activeSession.save();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in new issue
Block a user