Add curator roles/permissions with Users admin, and fix lineage branch joins.
Staff accounts use admin/curator roles and fine-grained flags; transitions connect source-to-target with color gradients and stream cutout masks so overlaps stay seamless. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
bfa21989c9
commit
0466b77328
@@ -1,5 +1,34 @@
|
||||
const pool = require('../db');
|
||||
const { hasPermission, effectivePermissions } = require('../permissions');
|
||||
|
||||
async function loadStaffUser(userId) {
|
||||
const { rows } = await pool.query(
|
||||
`SELECT id, username, role, permissions, is_active
|
||||
FROM users WHERE id = $1`,
|
||||
[userId]
|
||||
);
|
||||
if (rows.length === 0) return null;
|
||||
const row = rows[0];
|
||||
return {
|
||||
id: row.id,
|
||||
username: row.username,
|
||||
role: row.role,
|
||||
permissions: row.permissions || [],
|
||||
is_active: row.is_active !== false,
|
||||
};
|
||||
}
|
||||
|
||||
function attachStaff(req, user) {
|
||||
req.curatorUser = {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
role: user.role,
|
||||
permissions: user.permissions,
|
||||
is_active: user.is_active,
|
||||
};
|
||||
}
|
||||
|
||||
/** Any active staff account (admin or curator). */
|
||||
async function requireCurator(req, res, next) {
|
||||
const userId = req.session?.userId;
|
||||
if (!userId) {
|
||||
@@ -7,16 +36,13 @@ async function requireCurator(req, res, next) {
|
||||
}
|
||||
|
||||
try {
|
||||
const { rows } = await pool.query(
|
||||
`SELECT id, username FROM users WHERE id = $1`,
|
||||
[userId]
|
||||
);
|
||||
if (rows.length === 0) {
|
||||
const user = await loadStaffUser(userId);
|
||||
if (!user || !user.is_active) {
|
||||
req.session.destroy(() => {});
|
||||
return res.status(401).json({ error: 'Curator login required' });
|
||||
}
|
||||
|
||||
req.curatorUser = rows[0];
|
||||
attachStaff(req, user);
|
||||
next();
|
||||
} catch (err) {
|
||||
console.error('Auth middleware error:', err.message);
|
||||
@@ -24,4 +50,46 @@ async function requireCurator(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { requireCurator };
|
||||
/** Active staff with a specific permission (admins always pass). */
|
||||
function requirePermission(permission) {
|
||||
return async (req, res, next) => {
|
||||
const userId = req.session?.userId;
|
||||
if (!userId) {
|
||||
return res.status(401).json({ error: 'Curator login required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await loadStaffUser(userId);
|
||||
if (!user || !user.is_active) {
|
||||
req.session.destroy(() => {});
|
||||
return res.status(401).json({ error: 'Curator login required' });
|
||||
}
|
||||
|
||||
attachStaff(req, user);
|
||||
|
||||
if (!hasPermission(user, permission)) {
|
||||
return res.status(403).json({ error: 'Permission denied' });
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (err) {
|
||||
console.error('Auth middleware error:', err.message);
|
||||
res.status(500).json({ error: 'Authentication failed' });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function staffAuthPayload(user) {
|
||||
return {
|
||||
role: user.role,
|
||||
username: user.username,
|
||||
permissions: effectivePermissions(user),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
requireCurator,
|
||||
requirePermission,
|
||||
loadStaffUser,
|
||||
staffAuthPayload,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user