import joi from "joi"; //**************************************** // Custom Validators //**************************************** const roleValidatior = (role) => (value, helpers) => { const hasRole = role.some((role) => value.includes(role)); if (!hasRole) { throw new joi.ValidationError( `You do not have the required authorization. Required roles: ${role.join(", ")}` ); } return value; }; //**************************************** // Auth //**************************************** const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/])[A-Za-z0-9!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/]+$/; const loginValidation = joi.object({ email: joi .string() .email() .required() .custom((value, helpers) => { const lowercasedValue = value.toLowerCase(); if (value !== lowercasedValue) { return helpers.message("Email must be in lowercase"); } return lowercasedValue; }), password: joi.string().min(8).required().pattern(passwordPattern), }); const registrationBodyValidation = joi.object({ firstName: joi .string() .required() .pattern(/^[A-Za-z]+$/), lastName: joi .string() .required() .pattern(/^[A-Za-z]+$/), email: joi .string() .email() .required() .custom((value, helpers) => { const lowercasedValue = value.toLowerCase(); if (value !== lowercasedValue) { return helpers.message("Email must be in lowercase"); } return lowercasedValue; }), password: joi.string().min(8).required().pattern(passwordPattern), profileImage: joi.any(), role: joi .array() .items(joi.string().valid("superadmin", "admin", "user", "demo")) .min(1) .required(), teamId: joi.string().allow("").required(), inviteToken: joi.string().allow("").required(), }); const editUserParamValidation = joi.object({ userId: joi.string().required(), }); const editUserBodyValidation = joi.object({ firstName: joi.string().pattern(/^[A-Za-z]+$/), lastName: joi.string().pattern(/^[A-Za-z]+$/), profileImage: joi.any(), newPassword: joi.string().min(8).pattern(passwordPattern), password: joi.string().min(8).pattern(passwordPattern), deleteProfileImage: joi.boolean(), role: joi.array(), }); const recoveryValidation = joi.object({ email: joi .string() .email({ tlds: { allow: false } }) .required(), }); const recoveryTokenValidation = joi.object({ recoveryToken: joi.string().required(), }); const newPasswordValidation = joi.object({ recoveryToken: joi.string().required(), password: joi.string().min(8).required().pattern(passwordPattern), confirm: joi.string(), }); const deleteUserParamValidation = joi.object({ email: joi.string().email().required(), }); const inviteRoleValidation = joi.object({ roles: joi.custom(roleValidatior(["admin", "superadmin"])).required(), }); const inviteBodyValidation = joi.object({ email: joi.string().trim().email().required().messages({ "string.empty": "Email is required", "string.email": "Must be a valid email address", }), role: joi.array().required(), teamId: joi.string().required(), }); const inviteVerificationBodyValidation = joi.object({ token: joi.string().required(), }); //**************************************** // Monitors //**************************************** const getMonitorByIdParamValidation = joi.object({ monitorId: joi.string().required(), }); const getMonitorByIdQueryValidation = joi.object({ status: joi.boolean(), sortOrder: joi.string().valid("asc", "desc"), limit: joi.number(), dateRange: joi.string().valid("day", "week", "month"), numToDisplay: joi.number(), normalize: joi.boolean(), }); const getMonitorsAndSummaryByTeamIdParamValidation = joi.object({ teamId: joi.string().required(), }); const getMonitorsAndSummaryByTeamIdQueryValidation = joi.object({ type: joi .alternatives() .try( joi.string().valid("http", "ping", "pagespeed", "docker", "hardware"), joi .array() .items(joi.string().valid("http", "ping", "pagespeed", "docker", "hardware")) ), }); const getMonitorsByTeamIdValidation = joi.object({ teamId: joi.string().required(), }); const getMonitorsByTeamIdQueryValidation = joi.object({ status: joi.boolean(), checkOrder: joi.string().valid("asc", "desc"), limit: joi.number(), normalize: joi.boolean(), type: joi .alternatives() .try( joi.string().valid("http", "ping", "pagespeed", "docker", "hardware"), joi .array() .items(joi.string().valid("http", "ping", "pagespeed", "docker", "hardware")) ), page: joi.number(), rowsPerPage: joi.number(), filter: joi.string(), field: joi.string(), order: joi.string().valid("asc", "desc"), }); const getMonitorStatsByIdParamValidation = joi.object({ monitorId: joi.string().required(), }); const getMonitorStatsByIdQueryValidation = joi.object({ status: joi.string(), limit: joi.number(), sortOrder: joi.string().valid("asc", "desc"), dateRange: joi.string().valid("day", "week", "month", "all"), numToDisplay: joi.number(), normalize: joi.boolean(), }); const getCertificateParamValidation = joi.object({ monitorId: joi.string().required(), }); const createMonitorBodyValidation = joi.object({ _id: joi.string(), userId: joi.string().required(), teamId: joi.string().required(), name: joi.string().required(), description: joi.string().required(), type: joi.string().required(), url: joi.string().required(), isActive: joi.boolean(), interval: joi.number(), thresholds: joi.object().keys({ usage_cpu: joi.number(), usage_memory: joi.number(), usage_disk: joi.number(), }), notifications: joi.array().items(joi.object()), secret: joi.string(), }); const editMonitorBodyValidation = joi.object({ name: joi.string(), description: joi.string(), interval: joi.number(), notifications: joi.array().items(joi.object()), secret: joi.string(), }); const pauseMonitorParamValidation = joi.object({ monitorId: joi.string().required(), }); const getMonitorURLByQueryValidation = joi.object({ monitorURL: joi.string().uri().required(), }); //**************************************** // Alerts //**************************************** const createAlertParamValidation = joi.object({ monitorId: joi.string().required(), }); const createAlertBodyValidation = joi.object({ checkId: joi.string().required(), monitorId: joi.string().required(), userId: joi.string().required(), status: joi.boolean(), message: joi.string(), notifiedStatus: joi.boolean(), acknowledgeStatus: joi.boolean(), }); const getAlertsByUserIdParamValidation = joi.object({ userId: joi.string().required(), }); const getAlertsByMonitorIdParamValidation = joi.object({ monitorId: joi.string().required(), }); const getAlertByIdParamValidation = joi.object({ alertId: joi.string().required(), }); const editAlertParamValidation = joi.object({ alertId: joi.string().required(), }); const editAlertBodyValidation = joi.object({ status: joi.boolean(), message: joi.string(), notifiedStatus: joi.boolean(), acknowledgeStatus: joi.boolean(), }); const deleteAlertParamValidation = joi.object({ alertId: joi.string().required(), }); //**************************************** // Checks //**************************************** const createCheckParamValidation = joi.object({ monitorId: joi.string().required(), }); const createCheckBodyValidation = joi.object({ monitorId: joi.string().required(), status: joi.boolean().required(), responseTime: joi.number().required(), statusCode: joi.number().required(), message: joi.string().required(), }); const getChecksParamValidation = joi.object({ monitorId: joi.string().required(), }); const getChecksQueryValidation = joi.object({ sortOrder: joi.string().valid("asc", "desc"), limit: joi.number(), dateRange: joi.string().valid("day", "week", "month"), filter: joi.string().valid("all", "down", "resolve"), page: joi.number(), rowsPerPage: joi.number(), }); const getTeamChecksParamValidation = joi.object({ teamId: joi.string().required(), }); const getTeamChecksQueryValidation = joi.object({ sortOrder: joi.string().valid("asc", "desc"), limit: joi.number(), dateRange: joi.string().valid("day", "week", "month"), filter: joi.string().valid("all", "down", "resolve"), page: joi.number(), rowsPerPage: joi.number(), }); const deleteChecksParamValidation = joi.object({ monitorId: joi.string().required(), }); const deleteChecksByTeamIdParamValidation = joi.object({ teamId: joi.string().required(), }); const updateChecksTTLBodyValidation = joi.object({ ttl: joi.number().required(), }); //**************************************** // PageSpeedCheckValidation //**************************************** const getPageSpeedCheckParamValidation = joi.object({ monitorId: joi.string().required(), }); //Validation schema for the monitorId parameter const createPageSpeedCheckParamValidation = joi.object({ monitorId: joi.string().required(), }); //Validation schema for the monitorId body const createPageSpeedCheckBodyValidation = joi.object({ url: joi.string().required(), }); const deletePageSpeedCheckParamValidation = joi.object({ monitorId: joi.string().required(), }); //**************************************** // MaintenanceWindowValidation //**************************************** const createMaintenanceWindowBodyValidation = joi.object({ monitors: joi.array().items(joi.string()).required(), name: joi.string().required(), active: joi.boolean(), start: joi.date().required(), end: joi.date().required(), repeat: joi.number().required(), expiry: joi.date(), }); const getMaintenanceWindowByIdParamValidation = joi.object({ id: joi.string().required(), }); const getMaintenanceWindowsByTeamIdQueryValidation = joi.object({ active: joi.boolean(), page: joi.number(), rowsPerPage: joi.number(), field: joi.string(), order: joi.string().valid("asc", "desc"), }); const getMaintenanceWindowsByMonitorIdParamValidation = joi.object({ monitorId: joi.string().required(), }); const deleteMaintenanceWindowByIdParamValidation = joi.object({ id: joi.string().required(), }); const editMaintenanceWindowByIdParamValidation = joi.object({ id: joi.string().required(), }); const editMaintenanceByIdWindowBodyValidation = joi.object({ active: joi.boolean(), name: joi.string(), repeat: joi.number(), start: joi.date(), end: joi.date(), expiry: joi.date(), monitors: joi.array(), }); //**************************************** // SettingsValidation //**************************************** const updateAppSettingsBodyValidation = joi.object({ apiBaseUrl: joi.string().allow(""), logLevel: joi.string().valid("debug", "none", "error", "warn").allow(""), clientHost: joi.string().allow(""), dbType: joi.string().allow(""), dbConnectionString: joi.string().allow(""), redisHost: joi.string().allow(""), redisPort: joi.number().allow(null, ""), jwtTTL: joi.string().allow(""), pagespeedApiKey: joi.string().allow(""), systemEmailHost: joi.string().allow(""), systemEmailPort: joi.number().allow(""), systemEmailAddress: joi.string().allow(""), systemEmailPassword: joi.string().allow(""), }); //**************************************** // Status Page Validation //**************************************** const getStatusPageParamValidation = joi.object({ url: joi.string().required(), }); const createStatusPageBodyValidation = joi.object({ companyName: joi.string().required(), url: joi.string().required(), timezone: joi.string().required(), color: joi.string().required(), theme: joi.string().required(), monitors: joi .array() .items(joi.string().pattern(/^[0-9a-fA-F]{24}$/)) .required() .messages({ "string.pattern.base": "Must be a valid monitor ID", "array.base": "Monitors must be an array", "array.empty": "At least one monitor is required", "any.required": "Monitors are required", }), }); export { roleValidatior, loginValidation, registrationBodyValidation, recoveryValidation, recoveryTokenValidation, newPasswordValidation, inviteRoleValidation, inviteBodyValidation, inviteVerificationBodyValidation, createMonitorBodyValidation, getMonitorByIdParamValidation, getMonitorByIdQueryValidation, getMonitorsAndSummaryByTeamIdParamValidation, getMonitorsAndSummaryByTeamIdQueryValidation, getMonitorsByTeamIdValidation, getMonitorsByTeamIdQueryValidation, getMonitorStatsByIdParamValidation, getMonitorStatsByIdQueryValidation, getCertificateParamValidation, editMonitorBodyValidation, pauseMonitorParamValidation, getMonitorURLByQueryValidation, editUserParamValidation, editUserBodyValidation, createAlertParamValidation, createAlertBodyValidation, getAlertsByUserIdParamValidation, getAlertsByMonitorIdParamValidation, getAlertByIdParamValidation, editAlertParamValidation, editAlertBodyValidation, deleteAlertParamValidation, createCheckParamValidation, createCheckBodyValidation, getChecksParamValidation, getChecksQueryValidation, getTeamChecksParamValidation, getTeamChecksQueryValidation, deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, deleteUserParamValidation, getPageSpeedCheckParamValidation, createPageSpeedCheckParamValidation, deletePageSpeedCheckParamValidation, createPageSpeedCheckBodyValidation, createMaintenanceWindowBodyValidation, getMaintenanceWindowByIdParamValidation, getMaintenanceWindowsByTeamIdQueryValidation, getMaintenanceWindowsByMonitorIdParamValidation, deleteMaintenanceWindowByIdParamValidation, editMaintenanceWindowByIdParamValidation, editMaintenanceByIdWindowBodyValidation, updateAppSettingsBodyValidation, createStatusPageBodyValidation, getStatusPageParamValidation, };