Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | 3x 10x 41x 41x 41x 41x 5x 36x 2x 34x 36x 36x 6x 6x 30x 3x 3x 3x 3x 3x 3x 2x 2x 2x 2x 1x 3x | const { permissionChecker } = require('./PermissionChecker')
/**
* Middleware to check user permissions before executing Lambda handler
*
* @param {Function} handler - The actual Lambda handler function
* @param {Object} options - Configuration options
* @param {Function|string} options.permission - Permission string or function that returns permission string
* @param {Function} [options.resource] - Optional function to extract resource from event (for dynamic permissions)
* @returns {Function} Wrapped Lambda handler with permission check
*
* @example
* // Static permission
* exports.handler = requirePermission(async (event) => {
* // handler logic
* }, { permission: 'entity:create' });
*
* @example
* // Dynamic permission based on path parameter
* exports.handler = requirePermission(async (event) => {
* // handler logic
* }, {
* permission: (event) => `entity-${event.pathParameters.id}:read`
* });
*/
function requirePermission(handler, options) {
return async (event) => {
try {
// Extract user info from Cognito authorizer
const tenantId = event.requestContext?.authorizer?.claims?.['custom:tenantId']
const userId = event.requestContext?.authorizer?.claims?.sub
if (!userId || !tenantId) {
return {
statusCode: 401,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ error: 'Unauthorized - Missing authentication' })
}
}
// Determine required permission
let requiredPermission
if (typeof options.permission === 'function') {
requiredPermission = options.permission(event)
} else {
requiredPermission = options.permission
}
// Check permission
const result = await permissionChecker.hasPermission(userId, tenantId, requiredPermission)
if (!result.hasPermission) {
console.log(`Permission denied: User ${userId} lacks ${requiredPermission}`, result.reason)
return {
statusCode: 403,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
error: 'Forbidden - Insufficient permissions',
required: requiredPermission
})
}
}
// Permission granted, execute handler
return await handler(event)
} catch (error) {
console.error('Error in requirePermission middleware:', error)
return {
statusCode: 500,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ error: 'Internal server error' })
}
}
}
}
/**
* Helper to check permission without wrapping (for use inside handlers)
*/
async function checkPermission(event, permission) {
const tenantId = event.requestContext?.authorizer?.claims?.['custom:tenantId']
const userId = event.requestContext?.authorizer?.claims?.sub
Iif (!userId || !tenantId) {
throw new Error('Missing authentication context')
}
const requiredPermission = typeof permission === 'function' ? permission(event) : permission
const result = await permissionChecker.hasPermission(userId, tenantId, requiredPermission)
if (!result.hasPermission) {
const error = new Error('Insufficient permissions')
error.statusCode = 403
error.requiredPermission = requiredPermission
throw error
}
return true
}
module.exports = {
requirePermission,
checkPermission
}
|