Split adminCapabilities middleware into two

GitOrigin-RevId: 093e455e33459cae2e3da236958cb991f128299e
This commit is contained in:
Andrew Rumble
2025-08-08 08:05:52 +00:00
committed by Copybot
parent 0f4534260b
commit 70e0ca3eb5
3 changed files with 226 additions and 86 deletions
@@ -8,7 +8,8 @@ module.exports = {
hasAdminAccess,
canRedirectToAdminDomain,
getAdminCapabilities,
addHasAdminCapabilityToLocals: expressify(addHasAdminCapabilityToLocals),
useHasAdminCapability,
useAdminCapabilities: expressify(useAdminCapabilities),
}
function hasAdminAccess(user) {
@@ -29,26 +30,40 @@ async function getAdminCapabilities(user) {
}
}
async function addHasAdminCapabilityToLocals(req, res, next) {
async function useAdminCapabilities(req, res, next) {
if (req.adminCapabilities) {
return next()
}
const user = SessionManager.getSessionUser(req.session)
if (!hasAdminAccess(user)) {
res.locals.hasAdminCapability = () => false
req.adminCapabilities = []
return next()
}
try {
const { adminCapabilities, adminCapabilitiesAvailable } =
await getAdminCapabilities(user)
res.locals.hasAdminCapability = capability => {
if (!adminCapabilitiesAvailable) {
// If admin capabilities are not available, then all admins have all capabilities
return true
}
return adminCapabilities.includes(capability)
req.adminCapabilities = adminCapabilities
req.adminCapabilitiesAvailable = adminCapabilitiesAvailable
} catch (err) {
logger.warn({ err, req }, 'Failed to get admin capabilities')
req.adminCapabilities = []
// Admin capabilities are likely available because we shouldn't throw otherwise.
req.adminCapabilitiesAvailable = true
}
next()
}
function useHasAdminCapability(req, res, next) {
res.locals.hasAdminCapability = capability => {
if (!hasAdminAccess(SessionManager.getSessionUser(req.session))) {
return false
}
} catch (error) {
logger.warn({ error, req, user }, 'Failed to get admin capabilities')
// A module probably threw so adminCapabilitiesAvailable should be true if we are here so deny to be safe
res.locals.hasAdminCapability = () => false
const { adminCapabilitiesAvailable, adminCapabilities } = req
if (!adminCapabilitiesAvailable) {
// We can't know which capabilities are possible, so we assume all are available for admins.
return true
}
return adminCapabilities.includes(capability)
}
next()
}
@@ -13,9 +13,10 @@ const PackageVersions = require('./PackageVersions')
const Modules = require('./Modules')
const Errors = require('../Features/Errors/Errors')
const {
addHasAdminCapabilityToLocals,
canRedirectToAdminDomain,
hasAdminAccess,
useAdminCapabilities,
useHasAdminCapability,
} = require('../Features/Helpers/AdminAuthorizationHelper')
const {
addOptionalCleanupHandlerAfterDrainingConnections,
@@ -313,7 +314,9 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
next()
})
webRouter.use(addHasAdminCapabilityToLocals)
webRouter.use(useAdminCapabilities)
webRouter.use(useHasAdminCapability)
webRouter.use(function (req, res, next) {
// Clone the nav settings so they can be modified for each request