Source: utils/uuidValidation.js

/**
 * UUID Validation Middleware
 * 
 * Provides middleware functions to validate UUID parameters in Express routes.
 * This prevents undefined parameter errors when invalid UUIDs are passed to UUID2hex().
 * 
 * Usage:
 * - Apply as route middleware: api.delete('/:UID', validateSingleUID, handler)
 * - Apply as param middleware: api.param('UID', validateUUIDParam)
 * - Validate multiple params: validateUUID(['UID', 'UIDparent', 'UIDperson'])
 */

import { isValidUID } from './UUIDs.js';

/**
 * Validates UUID parameters in the request
 * @param {string[]} paramNames - Array of parameter names to validate
 * @returns {Function} Express middleware function
 * 
 * @example
 * // Validate single parameter
 * api.delete('/:UID', validateUUID(['UID']), controller.delete);
 * 
 * @example
 * // Validate multiple parameters
 * api.put('/:member/:group', validateUUID(['member', 'group']), controller.update);
 */
export const validateUUID = (paramNames = ['UID']) => {
    return (req, res, next) => {
        const invalidParams = [];
        
        for (const paramName of paramNames) {
            const uid = req.params[paramName];
            
            // Only validate if parameter exists (some routes have optional params)
            if (uid && !isValidUID(uid)) {
                invalidParams.push(paramName);
            }
        }
        
        if (invalidParams.length > 0) {
            return res.status(400).json({ 
                success: false, 
                message: `Invalid UUID format for parameter${invalidParams.length > 1 ? 's' : ''}: ${invalidParams.join(', ')}`,
                error: 'INVALID_UUID',
                params: invalidParams
            });
        }
        
        next();
    };
};

/**
 * Convenience middleware for validating a single UID parameter
 * Most common use case for DELETE, GET, POST endpoints
 * 
 * @example
 * api.delete('/:UID', validateSingleUID, controller.delete);
 */
export const validateSingleUID = validateUUID(['UID']);

/**
 * Convenience middleware for validating multiple common UUID parameters
 * Useful for endpoints that accept multiple UIDs
 * 
 * @example
 * api.put('/:member/:group/:function', validateMultipleUIDs, controller.create);
 */
export const validateMultipleUIDs = validateUUID([
    'UID', 
    'UIDparent', 
    'UIDperson', 
    'UIDmember',
    'UIDgroup', 
    'UIDfamily',
    'UIDfunction',
    'member',
    'group',
    'function',
    'template'
]);

/**
 * Express param middleware for automatic validation
 * Apply this to automatically validate any route parameter
 * 
 * @param {string} paramName - The parameter name to validate (e.g., 'UID')
 * @returns {Function} Express param middleware function
 * 
 * @example
 * // Automatically validate all :UID parameters in this router
 * api.param('UID', validateUUIDParam('UID'));
 * 
 * // Now all routes with :UID are automatically protected
 * api.delete('/:UID', controller.delete);
 * api.get('/:UID', controller.get);
 */
export const validateUUIDParam = (paramName = 'UID') => {
    return (req, res, next, value) => {
        if (!isValidUID(value)) {
            return res.status(400).json({ 
                success: false, 
                message: `Invalid UUID format for parameter: ${paramName}`,
                error: 'INVALID_UUID',
                param: paramName,
                value: value
            });
        }
        next();
    };
};

/**
 * Validator for query parameters (not route params)
 * Some endpoints receive UIDs in query strings
 * 
 * @param {string[]} queryNames - Array of query parameter names to validate
 * @returns {Function} Express middleware function
 * 
 * @example
 * api.get('/search', validateQueryUUID(['user', 'loginUser']), controller.search);
 */
export const validateQueryUUID = (queryNames = []) => {
    return (req, res, next) => {
        const invalidParams = [];
        
        for (const queryName of queryNames) {
            const uid = req.query[queryName];
            
            // Only validate if query param exists
            if (uid && !isValidUID(uid)) {
                invalidParams.push(queryName);
            }
        }
        
        if (invalidParams.length > 0) {
            return res.status(400).json({ 
                success: false, 
                message: `Invalid UUID format for query parameter${invalidParams.length > 1 ? 's' : ''}: ${invalidParams.join(', ')}`,
                error: 'INVALID_UUID',
                params: invalidParams
            });
        }
        
        next();
    };
};

/**
 * Validator for request body UIDs
 * Some endpoints receive UIDs in the request body
 * 
 * @param {string[]} bodyFields - Array of body field names to validate
 * @param {boolean} required - Whether the fields are required (default: false)
 * @returns {Function} Express middleware function
 * 
 * @example
 * api.put('/', validateBodyUUID(['UID', 'UIDparent'], false), controller.create);
 */
export const validateBodyUUID = (bodyFields = [], required = false) => {
    return (req, res, next) => {
        const invalidFields = [];
        const missingFields = [];
        
        for (const fieldName of bodyFields) {
            const uid = req.body[fieldName];
            
            if (!uid) {
                if (required) {
                    missingFields.push(fieldName);
                }
                continue;
            }
            
            if (!isValidUID(uid)) {
                invalidFields.push(fieldName);
            }
        }
        
        if (missingFields.length > 0) {
            return res.status(400).json({ 
                success: false, 
                message: `Missing required UUID field${missingFields.length > 1 ? 's' : ''}: ${missingFields.join(', ')}`,
                error: 'MISSING_UUID',
                fields: missingFields
            });
        }
        
        if (invalidFields.length > 0) {
            return res.status(400).json({ 
                success: false, 
                message: `Invalid UUID format for field${invalidFields.length > 1 ? 's' : ''}: ${invalidFields.join(', ')}`,
                error: 'INVALID_UUID',
                fields: invalidFields
            });
        }
        
        next();
    };
};