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

+126
View File
@@ -0,0 +1,126 @@
// backend/routes/auth/sessions.js
// ─────────────────────────────────────────────────────────────────────────────
// User Session Management Routes (Active Sessions & Remote Revocation)
// ─────────────────────────────────────────────────────────────────────────────
const express = require('express');
const router = express.Router();
const User = require('../../models/User');
const Session = require('../../models/Session');
const { requireAuth, requireAdmin } = require('./helpers');
// Helper to block SOC_ANALYST from write actions
function blockAnalyst(req, res, next) {
if (req.adminUser.role === 'SOC_ANALYST') {
return res.status(403).json({ ok: false, error: 'Aksi ini tidak diizinkan untuk peran SOC Analyst' });
}
next();
}
// ─── GET /api/auth/sessions (Current User Sessions) ──────────────────────────
router.get('/sessions', requireAuth, async (req, res) => {
try {
const sessions = await Session.find({ user_id: req.user.id }).sort({ last_active: -1 });
const data = sessions.map(s => ({
id: s._id.toString(),
ip_address: s.ip_address,
user_agent: s.user_agent,
last_active: s.last_active,
created_at: s.created_at,
is_current: req.user.session_id === s._id.toString(),
}));
res.json({ ok: true, data });
} catch (err) {
res.status(500).json({ ok: false, error: err.message });
}
});
// ─── DELETE /api/auth/sessions/:id (Revoke Current User Session) ──────────────
router.delete('/sessions/:id', requireAuth, async (req, res) => {
try {
const session = await Session.findById(req.params.id);
if (!session) {
return res.status(404).json({ ok: false, error: 'Sesi tidak ditemukan' });
}
// Users can only revoke their own sessions
if (session.user_id.toString() !== req.user.id) {
return res.status(403).json({ ok: false, error: 'Aksi dilarang' });
}
await Session.findByIdAndDelete(req.params.id);
// Clear cookies if the user revokes their own current session
if (req.user.session_id === req.params.id) {
res.clearCookie('token');
}
res.json({ ok: true, message: 'Sesi berhasil diakhiri' });
} catch (err) {
res.status(500).json({ ok: false, error: err.message });
}
});
// ─── GET /api/auth/admin/sessions (Tenant/All Sessions) ──────────────────────
router.get('/admin/sessions', requireAdmin, async (req, res) => {
try {
let userQuery = {};
if (req.adminUser.role === 'TENANT_ADMIN') {
userQuery = { site_uuid: req.adminUser.site_uuid };
}
const users = await User.find(userQuery, 'username role account_name site_uuid');
const userIds = users.map(u => u._id);
const sessions = await Session.find({ user_id: { $in: userIds } })
.populate('user_id', 'username role account_name site_uuid')
.sort({ last_active: -1 });
const data = sessions.map(s => {
const u = s.user_id || {};
return {
id: s._id.toString(),
username: u.username || 'Unknown',
role: u.role || 'Unknown',
account_name: u.account_name || 'Unknown',
site_uuid: u.site_uuid || null,
ip_address: s.ip_address,
user_agent: s.user_agent,
last_active: s.last_active,
created_at: s.created_at,
is_current: req.adminUser.session_id === s._id.toString(),
};
});
res.json({ ok: true, data });
} catch (err) {
res.status(500).json({ ok: false, error: err.message });
}
});
// ─── DELETE /api/auth/admin/sessions/:id (Revoke Any Session by Admin) ───────
router.delete('/admin/sessions/:id', requireAdmin, blockAnalyst, async (req, res) => {
try {
const session = await Session.findById(req.params.id).populate('user_id');
if (!session) {
return res.status(404).json({ ok: false, error: 'Sesi tidak ditemukan' });
}
// Tenant Admin can only revoke sessions within their own site
if (req.adminUser.role !== 'SUPER_ADMIN') {
const sessionUser = session.user_id || {};
if (sessionUser.site_uuid !== req.adminUser.site_uuid) {
return res.status(403).json({ ok: false, error: 'Unauthorized: Sesi berada di luar site Anda' });
}
}
await Session.findByIdAndDelete(req.params.id);
res.json({ ok: true, message: 'Sesi berhasil diakhiri oleh administrator' });
} catch (err) {
res.status(500).json({ ok: false, error: err.message });
}
});
module.exports = router;