Initial Claude Run
This commit is contained in:
164
backend/src/utils/validation.js
Normal file
164
backend/src/utils/validation.js
Normal file
@@ -0,0 +1,164 @@
|
||||
const Joi = require('joi');
|
||||
|
||||
// User validation schemas
|
||||
const registerSchema = Joi.object({
|
||||
email: Joi.string().email().required(),
|
||||
password: Joi.string().min(8).pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/).required()
|
||||
.messages({
|
||||
'string.pattern.base': 'Password must contain at least one lowercase letter, one uppercase letter, one number, and one special character'
|
||||
}),
|
||||
firstName: Joi.string().max(100).required(),
|
||||
lastName: Joi.string().max(100).required()
|
||||
});
|
||||
|
||||
const loginSchema = Joi.object({
|
||||
email: Joi.string().email().required(),
|
||||
password: Joi.string().required()
|
||||
});
|
||||
|
||||
const updateUserSchema = Joi.object({
|
||||
firstName: Joi.string().max(100),
|
||||
lastName: Joi.string().max(100),
|
||||
email: Joi.string().email()
|
||||
});
|
||||
|
||||
const changePasswordSchema = Joi.object({
|
||||
currentPassword: Joi.string().required(),
|
||||
newPassword: Joi.string().min(8).pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/).required()
|
||||
.messages({
|
||||
'string.pattern.base': 'Password must contain at least one lowercase letter, one uppercase letter, one number, and one special character'
|
||||
})
|
||||
});
|
||||
|
||||
// Property validation schemas
|
||||
const propertySchema = Joi.object({
|
||||
name: Joi.string().max(255).required(),
|
||||
address: Joi.string().max(500),
|
||||
latitude: Joi.number().min(-90).max(90),
|
||||
longitude: Joi.number().min(-180).max(180),
|
||||
totalArea: Joi.number().positive()
|
||||
});
|
||||
|
||||
const lawnSectionSchema = Joi.object({
|
||||
name: Joi.string().max(255).required(),
|
||||
area: Joi.number().positive().required(),
|
||||
polygonData: Joi.object(),
|
||||
grassType: Joi.string().max(100),
|
||||
soilType: Joi.string().max(100)
|
||||
});
|
||||
|
||||
// Equipment validation schemas
|
||||
const equipmentSchema = Joi.object({
|
||||
equipmentTypeId: Joi.number().integer().positive().required(),
|
||||
customName: Joi.string().max(255),
|
||||
tankSize: Joi.number().positive(),
|
||||
pumpGpm: Joi.number().positive(),
|
||||
nozzleGpm: Joi.number().positive(),
|
||||
nozzleCount: Joi.number().integer().positive(),
|
||||
spreaderWidth: Joi.number().positive()
|
||||
});
|
||||
|
||||
// Product validation schemas
|
||||
const productSchema = Joi.object({
|
||||
name: Joi.string().max(255).required(),
|
||||
brand: Joi.string().max(100),
|
||||
categoryId: Joi.number().integer().positive().required(),
|
||||
productType: Joi.string().valid('granular', 'liquid').required(),
|
||||
activeIngredients: Joi.string(),
|
||||
description: Joi.string()
|
||||
});
|
||||
|
||||
const productRateSchema = Joi.object({
|
||||
applicationType: Joi.string().max(100).required(),
|
||||
rateAmount: Joi.number().positive().required(),
|
||||
rateUnit: Joi.string().max(50).required(),
|
||||
notes: Joi.string()
|
||||
});
|
||||
|
||||
const userProductSchema = Joi.object({
|
||||
productId: Joi.number().integer().positive(),
|
||||
customName: Joi.string().max(255),
|
||||
customRateAmount: Joi.number().positive(),
|
||||
customRateUnit: Joi.string().max(50),
|
||||
notes: Joi.string()
|
||||
});
|
||||
|
||||
// Application validation schemas
|
||||
const applicationPlanSchema = Joi.object({
|
||||
lawnSectionId: Joi.number().integer().positive().required(),
|
||||
equipmentId: Joi.number().integer().positive().required(),
|
||||
plannedDate: Joi.date().required(),
|
||||
notes: Joi.string(),
|
||||
products: Joi.array().items(Joi.object({
|
||||
productId: Joi.number().integer().positive(),
|
||||
userProductId: Joi.number().integer().positive(),
|
||||
rateAmount: Joi.number().positive().required(),
|
||||
rateUnit: Joi.string().max(50).required()
|
||||
})).min(1).required()
|
||||
});
|
||||
|
||||
const applicationLogSchema = Joi.object({
|
||||
planId: Joi.number().integer().positive(),
|
||||
lawnSectionId: Joi.number().integer().positive().required(),
|
||||
equipmentId: Joi.number().integer().positive().required(),
|
||||
weatherConditions: Joi.object(),
|
||||
gpsTrack: Joi.object(),
|
||||
averageSpeed: Joi.number().positive(),
|
||||
areaCovered: Joi.number().positive(),
|
||||
notes: Joi.string(),
|
||||
products: Joi.array().items(Joi.object({
|
||||
productId: Joi.number().integer().positive(),
|
||||
userProductId: Joi.number().integer().positive(),
|
||||
rateAmount: Joi.number().positive().required(),
|
||||
rateUnit: Joi.string().max(50).required(),
|
||||
actualProductAmount: Joi.number().positive(),
|
||||
actualWaterAmount: Joi.number().positive(),
|
||||
actualSpeedMph: Joi.number().positive()
|
||||
})).min(1).required()
|
||||
});
|
||||
|
||||
// Validation middleware
|
||||
const validateRequest = (schema) => {
|
||||
return (req, res, next) => {
|
||||
const { error } = schema.validate(req.body, { abortEarly: false });
|
||||
if (error) {
|
||||
return next(error);
|
||||
}
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
const validateParams = (schema) => {
|
||||
return (req, res, next) => {
|
||||
const { error } = schema.validate(req.params, { abortEarly: false });
|
||||
if (error) {
|
||||
return next(error);
|
||||
}
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
const idParamSchema = Joi.object({
|
||||
id: Joi.number().integer().positive().required()
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
// Schemas
|
||||
registerSchema,
|
||||
loginSchema,
|
||||
updateUserSchema,
|
||||
changePasswordSchema,
|
||||
propertySchema,
|
||||
lawnSectionSchema,
|
||||
equipmentSchema,
|
||||
productSchema,
|
||||
productRateSchema,
|
||||
userProductSchema,
|
||||
applicationPlanSchema,
|
||||
applicationLogSchema,
|
||||
idParamSchema,
|
||||
|
||||
// Middleware
|
||||
validateRequest,
|
||||
validateParams
|
||||
};
|
||||
Reference in New Issue
Block a user