feat: implement internal and user security middlewares and refactor route structures to support view and API separation

This commit is contained in:
Giuseppe Raffa
2026-04-04 19:11:29 +02:00
parent 0f511c2cf9
commit 3cd5a84cc1
8 changed files with 83 additions and 42 deletions

View File

@@ -0,0 +1,12 @@
const API_KEY = process.env.INTERNAL_API_KEY;
const internalAuth = (req, res, next) => {
const internalToken = req.headers['x-internal-api-key'];
if (internalToken === API_KEY) {
req.user = { id: 'system', role: 'internal_service' };
return next();
}
return res.status(403).json({ error: 'Accesso negato: Richiesta interna non autorizzata' });
};
module.exports = internalAuth;

View File

@@ -0,0 +1,22 @@
const jwt = require('../tools/jwt');
const userAuth = (req, res, next) => {
const token = (req.cookies && req.cookies.auth_token) || jwt.getToken(req.headers['authorization']);
if (!token) {
return res.status(401).json({ error: 'Accesso negato: Token utente mancante' });
}
const verified = jwt.verifyToken(token);
if (!verified.valid) {
return res.status(401).json({
error: 'Sessione non valida o scaduta',
reason: verified.reason
});
}
req.user = verified.payload;
next();
};
module.exports = userAuth;

View File

@@ -2,22 +2,9 @@ const router = require('express').Router();
const auth = require('../core/auth.core'); const auth = require('../core/auth.core');
const jwt = require('../tools/jwt'); const jwt = require('../tools/jwt');
const version = process.env.VERSION;
const vBuild = process.env.VERSION_BUILD;
const vState = process.env.VERSION_STATE;
const CONSOLE_URL = process.env.CONSOLE_URL || 'http://localhost:3004'; const CONSOLE_URL = process.env.CONSOLE_URL || 'http://localhost:3004';
const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN || undefined; const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN || undefined;
router.get('/health', (req, res) => {
res.json({
status: 'ok',
service: 'auth',
version: version,
build_number: vBuild,
version_state: vState
});
});
router.post('/register', async (req, res) => { router.post('/register', async (req, res) => {
const { username, password } = req.body; const { username, password } = req.body;
@@ -36,10 +23,7 @@ router.post('/register', async (req, res) => {
} }
}); });
router.get('/login', (req, res) => {
const redirect = req.query.redirect || '';
res.render('loginpage', { error: null, redirect });
});
router.post('/login', async (req, res) => { router.post('/login', async (req, res) => {
const { username, password, redirect } = req.body; const { username, password, redirect } = req.body;

View File

@@ -0,0 +1,20 @@
// api.mebboat.it/api/sessions
const router = require('express').Router();
const { query } = require('../storage/database');
const userAuth = require('../middlewares/user.security');
router.use(userAuth);
router.get('/', async (req, res) => {
try {
const result = await query(
'SELECT id, user_id, session_code FROM sessions'
);
res.json(result.rows);
} catch (err) {
res.status(500).json({ error: 'Errore interno del server ' + err });
}
});
module.exports = router;

View File

@@ -1,32 +1,11 @@
// api.mebboat.it/users // api.mebboat.it/users
const router = require('express').Router(); const router = require('express').Router();
const jwt = require('../tools/jwt');
const { query } = require('../storage/database'); const { query } = require('../storage/database');
const userAuth = require('../middlewares/user.security');
const internalAuth = require('../middlewares/internal.security');
// Middleware di autenticazione: estrae l'utente dal token JWT router.get('/', internalAuth, async (req, res) => {
const requireAuth = (req, res, next) => {
// Estraiamo il token dai cookies (inserito al login) o dall'header "Authorization"
const token = (req.cookies && req.cookies.auth_token) || jwt.getToken(req.headers['authorization']);
if (!token) {
return res.status(401).json({ error: 'Non autorizzato: token mancante' });
}
const verified = jwt.verifyToken(token);
if (!verified.valid) {
return res.status(401).json({ error: 'Non autorizzato: token scaduto o non valido', reason: verified.reason });
}
// Il riferimento all'identità dell'utente viene agganciato all'oggetto `req`
// (payload conterrà { user_id, username, session_id })
req.user = verified.payload;
next();
};
router.use(requireAuth);
router.get('/', async (req, res) => {
try { try {
const result = await query( const result = await query(
'SELECT id, username, is_active, created_at, telegram_id FROM users' 'SELECT id, username, is_active, created_at, telegram_id FROM users'
@@ -37,7 +16,7 @@ router.get('/', async (req, res) => {
} }
}) })
router.get('/tonotify/', async (req, res) => { router.get('/tonotify', internalAuth, async (req, res) => {
try { try {
const result = await query( const result = await query(
'SELECT telegram_id FROM users WHERE telegram_id IS NOT NULL' 'SELECT telegram_id FROM users WHERE telegram_id IS NOT NULL'
@@ -48,6 +27,8 @@ router.get('/tonotify/', async (req, res) => {
} }
}) })
router.use(userAuth);
router.get('/me', async (req, res) => { router.get('/me', async (req, res) => {
try { try {
const result = await query( const result = await query(

View File

@@ -0,0 +1,8 @@
const router = require('express').Router();
router.get('/login', (req, res) => {
const redirect = req.query.redirect || '';
res.render('loginpage', { error: null, redirect });
});
module.exports = router;

View File

@@ -0,0 +1,7 @@
const router = require('express').Router();
router.get('/', userAuth, (req, res) => {
res.render('sessions');
});
module.exports = router;

View File

@@ -0,0 +1,7 @@
const router = require('express').Router();
router.get('/', (req, res) => {
res.render('user');
});
module.exports = router;