Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
104 lines
2.6 KiB
JavaScript
104 lines
2.6 KiB
JavaScript
import { validationResult } from 'express-validator';
|
|
import { logger } from '../utils/logger.js';
|
|
|
|
// Validate request middleware
|
|
export const validateRequest = (validations) => {
|
|
return async (req, res, next) => {
|
|
// Run all validations
|
|
await Promise.all(validations.map(validation => validation.run(req)));
|
|
|
|
const errors = validationResult(req);
|
|
if (errors.isEmpty()) {
|
|
return next();
|
|
}
|
|
|
|
const extractedErrors = [];
|
|
errors.array().map(err => extractedErrors.push({
|
|
field: err.path,
|
|
message: err.msg,
|
|
value: err.value
|
|
}));
|
|
|
|
logger.warn('Validation errors', {
|
|
path: req.path,
|
|
errors: extractedErrors
|
|
});
|
|
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Validation failed',
|
|
errors: extractedErrors
|
|
});
|
|
};
|
|
};
|
|
|
|
// Custom validators
|
|
export const validators = {
|
|
// Validate MongoDB ObjectId
|
|
isMongoId: (value) => {
|
|
const mongoIdRegex = /^[0-9a-fA-F]{24}$/;
|
|
return mongoIdRegex.test(value);
|
|
},
|
|
|
|
// Validate currency code
|
|
isCurrency: (value) => {
|
|
const validCurrencies = ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CNY'];
|
|
return validCurrencies.includes(value.toUpperCase());
|
|
},
|
|
|
|
// Validate credit card number (basic check)
|
|
isCreditCard: (value) => {
|
|
const cardRegex = /^[0-9]{13,19}$/;
|
|
return cardRegex.test(value.replace(/\s/g, ''));
|
|
},
|
|
|
|
// Validate phone number
|
|
isPhoneNumber: (value) => {
|
|
const phoneRegex = /^\+?[1-9]\d{1,14}$/;
|
|
return phoneRegex.test(value);
|
|
},
|
|
|
|
// Validate date range
|
|
isValidDateRange: (startDate, endDate) => {
|
|
const start = new Date(startDate);
|
|
const end = new Date(endDate);
|
|
return start <= end;
|
|
},
|
|
|
|
// Validate billing cycle
|
|
isBillingCycle: (value) => {
|
|
const validCycles = ['monthly', 'quarterly', 'yearly'];
|
|
return validCycles.includes(value);
|
|
},
|
|
|
|
// Validate plan type
|
|
isPlanType: (value) => {
|
|
const validPlans = ['free', 'starter', 'professional', 'enterprise', 'custom'];
|
|
return validPlans.includes(value);
|
|
}
|
|
};
|
|
|
|
// Sanitization helpers
|
|
export const sanitize = {
|
|
// Clean string input
|
|
cleanString: (value) => {
|
|
if (typeof value !== 'string') return value;
|
|
return value.trim().replace(/[<>]/g, '');
|
|
},
|
|
|
|
// Format currency amount
|
|
formatAmount: (value) => {
|
|
const amount = parseFloat(value);
|
|
return Math.round(amount * 100) / 100;
|
|
},
|
|
|
|
// Normalize email
|
|
normalizeEmail: (email) => {
|
|
return email.toLowerCase().trim();
|
|
},
|
|
|
|
// Clean credit card number
|
|
cleanCardNumber: (value) => {
|
|
return value.replace(/\s/g, '').replace(/-/g, '');
|
|
}
|
|
}; |