Add curator authentication with audit logging and fix empty 3D gallery sessions.

Introduce session-based curator login, gate debug/checkup routes, log mutations to curator_audit_log, and keep guest hall preload public. Fix gallery view mounting so WebGL halls render reliably after navigation.
This commit is contained in:
Danila Khodjaef
2026-07-06 00:17:01 +03:00
parent aa31a2aa6e
commit 9da065acbe
27 changed files with 1252 additions and 112 deletions
+80
View File
@@ -0,0 +1,80 @@
const express = require('express');
const bcrypt = require('bcryptjs');
const pool = require('../db');
const router = express.Router();
router.get('/me', async (req, res) => {
const userId = req.session?.userId;
if (!userId) {
return res.json({ role: 'user' });
}
try {
const { rows } = await pool.query(
`SELECT id, username FROM users WHERE id = $1`,
[userId]
);
if (rows.length === 0) {
req.session.destroy(() => {});
return res.json({ role: 'user' });
}
res.json({
role: 'curator',
username: rows[0].username,
});
} catch (err) {
console.error('Auth me error:', err.message);
res.status(500).json({ error: 'Failed to read session' });
}
});
router.post('/login', async (req, res) => {
const { username, password } = req.body ?? {};
if (!username || typeof username !== 'string' || !password || typeof password !== 'string') {
return res.status(400).json({ error: 'Username and password required' });
}
try {
const { rows } = await pool.query(
`SELECT id, username, password_hash FROM users WHERE username = $1`,
[username.trim()]
);
if (rows.length === 0) {
return res.status(401).json({ error: 'Invalid username or password' });
}
const user = rows[0];
const valid = await bcrypt.compare(password, user.password_hash);
if (!valid) {
return res.status(401).json({ error: 'Invalid username or password' });
}
await pool.query(`UPDATE users SET last_login_at = NOW() WHERE id = $1`, [user.id]);
req.session.userId = user.id;
req.session.username = user.username;
res.json({
role: 'curator',
username: user.username,
});
} catch (err) {
console.error('Auth login error:', err.message);
res.status(500).json({ error: 'Login failed' });
}
});
router.post('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
console.error('Auth logout error:', err.message);
return res.status(500).json({ error: 'Logout failed' });
}
res.clearCookie('gallery.sid');
res.json({ ok: true });
});
});
module.exports = router;