Implement RBAC roles system

This commit is contained in:
2026-07-21 21:05:02 +01:00
parent 7973ee0ea4
commit e051958bea
35 changed files with 2338 additions and 2257 deletions
+51 -6
View File
@@ -15,6 +15,8 @@ const registerAdminManageRoutes = require('./web/routes/admin-manage');
const registerAdminScreenCommandRoutes = require('./web/routes/admin-screen-commands');
const registerAdminContentRoutes = require('./web/routes/admin-content');
const { createWebBootstrap } = require('./web/bootstrap');
const { requirePermission } = require('./rbac');
const rbacData = require('./web/rbac-data');
const { createPlayerActionService } = require('./web/player-actions');
const { isClientNameAvailable, withClientNameReservation } = require('./client-name-check');
const { createSessionService } = require('./web/session');
@@ -130,6 +132,7 @@ async function start() {
pool: pool,
common: common,
pages: pages,
requirePermission: requirePermission,
buildDashboardState: webBootstrap.buildDashboardState
});
@@ -149,7 +152,10 @@ async function start() {
pages: pages,
formatDashboardDate: formatDashboardDate,
getAuditUserId: getAuditUserId,
hashPassword: hashPassword
hashPassword: hashPassword,
readArrayField: readArrayField,
rbacData: rbacData,
requirePermission: requirePermission
});
registerAdminManageRoutes(app, {
@@ -172,7 +178,8 @@ async function start() {
getScreenConnections: playerActionService.getScreenConnections,
getPlaylistDeleteBlockMessage: playerActionService.getPlaylistDeleteBlockMessage,
forwardPlayerCommand: playerActionService.forwardPlayerCommand,
playerPublicBaseUrl: PLAYER_PUBLIC_BASE_URL
playerPublicBaseUrl: PLAYER_PUBLIC_BASE_URL,
requirePermission: requirePermission
});
registerAdminScreenCommandRoutes(app, {
@@ -180,7 +187,19 @@ async function start() {
forwardPlayerCommand: playerActionService.forwardPlayerCommand,
getScreenConnections: playerActionService.getScreenConnections,
isClientNameAvailable: isClientNameAvailable,
withClientNameReservation: withClientNameReservation
withClientNameReservation: withClientNameReservation,
requirePermission: requirePermission
});
const registerAdminRbacRoutes = require('./web/routes/admin-rbac');
registerAdminRbacRoutes(app, {
pool: pool,
pages: pages,
getAuditUserId: getAuditUserId,
rbacData: rbacData,
permissions: require('./rbac').PERMISSIONS,
normalizePermissionKeys: require('./rbac').normalizePermissionKeys,
requirePermission: requirePermission
});
registerAdminContentRoutes(app, {
@@ -201,13 +220,39 @@ async function start() {
broadcastDashboardState: broadcastDashboardState,
getSlideDeleteBlockMessage: playerActionService.getSlideDeleteBlockMessage,
getTemplateDeleteBlockMessage: playerActionService.getTemplateDeleteBlockMessage,
getCanvasSizeDeleteBlockMessage: playerActionService.getCanvasSizeDeleteBlockMessage
getCanvasSizeDeleteBlockMessage: playerActionService.getCanvasSizeDeleteBlockMessage,
requirePermission: requirePermission
});
app.use(function (error, _req, res, _next) {
app.use(function (error, req, res, _next) {
console.error(error);
res.status(error.statusCode || 500).send(error.statusCode ? error.message : 'Internal server error');
const statusCode = Number(error && (error.statusCode || error.status)) || 500;
const wantsHtml = !String(req.originalUrl || '').startsWith('/api/') && (!req.accepts || req.accepts('html'));
if (wantsHtml && pages.renderErrorPage) {
const isPermissionError = statusCode === 403;
const message = isPermissionError
? String(error && error.message ? error.message : 'You do not have permission to access this area.')
: String(error && error.message ? error.message : 'An unexpected error occurred.');
const title = isPermissionError
? 'Access denied'
: statusCode === 404
? 'Not found'
: 'Something went wrong';
return res.status(statusCode).send(pages.renderErrorPage({
statusCode: statusCode,
title: title,
errorTitle: title,
message: message,
detail: statusCode >= 500 ? 'The server could not complete the request.' : '',
backUrl: req.currentUser ? '/admin' : '/login',
backLabel: req.currentUser ? 'Back to dashboard' : 'Sign in'
}, req.currentUser));
}
res.status(statusCode).send(statusCode >= 500 ? 'Internal server error' : String(error && error.message ? error.message : 'Error'));
});
// Ensure schema and mirror uploads before the web service starts handling traffic.