first commit: Complete phishing test management panel with Node.js backend and React frontend

This commit is contained in:
salvacybersec
2025-11-10 17:00:40 +03:00
commit 19e551f33b
77 changed files with 6677 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
const Joi = require('joi');
const loginSchema = Joi.object({
username: Joi.string()
.min(3)
.max(100)
.required()
.messages({
'string.empty': 'Username is required',
'string.min': 'Username must be at least 3 characters',
'string.max': 'Username must not exceed 100 characters',
}),
password: Joi.string()
.min(6)
.required()
.messages({
'string.empty': 'Password is required',
'string.min': 'Password must be at least 6 characters',
}),
});
const validate = (schema) => {
return (req, res, next) => {
const { error } = schema.validate(req.body, { abortEarly: false });
if (error) {
return res.status(400).json({
success: false,
error: 'Validation error',
details: error.details.map(d => d.message),
});
}
next();
};
};
module.exports = {
validateLogin: validate(loginSchema),
};

View File

@@ -0,0 +1,67 @@
const Joi = require('joi');
const createCompanySchema = Joi.object({
name: Joi.string()
.min(2)
.max(255)
.required()
.messages({
'string.empty': 'Company name is required',
'string.min': 'Company name must be at least 2 characters',
}),
description: Joi.string()
.max(1000)
.allow(null, '')
.optional(),
logo_url: Joi.string()
.uri()
.allow(null, '')
.optional(),
industry: Joi.string()
.max(100)
.allow(null, '')
.optional(),
});
const updateCompanySchema = Joi.object({
name: Joi.string()
.min(2)
.max(255)
.optional(),
description: Joi.string()
.max(1000)
.allow(null, '')
.optional(),
logo_url: Joi.string()
.uri()
.allow(null, '')
.optional(),
industry: Joi.string()
.max(100)
.allow(null, '')
.optional(),
active: Joi.boolean()
.optional(),
});
const validate = (schema) => {
return (req, res, next) => {
const { error } = schema.validate(req.body, { abortEarly: false });
if (error) {
return res.status(400).json({
success: false,
error: 'Validation error',
details: error.details.map(d => d.message),
});
}
next();
};
};
module.exports = {
validateCreateCompany: validate(createCompanySchema),
validateUpdateCompany: validate(updateCompanySchema),
};

View File

@@ -0,0 +1,59 @@
const Joi = require('joi');
const createTokenSchema = Joi.object({
company_id: Joi.number()
.integer()
.positive()
.required()
.messages({
'number.base': 'Company ID must be a number',
'any.required': 'Company ID is required',
}),
target_email: Joi.string()
.email()
.required()
.messages({
'string.email': 'Valid email is required',
'any.required': 'Target email is required',
}),
employee_name: Joi.string()
.max(255)
.allow(null, '')
.optional(),
template_type: Joi.string()
.max(50)
.default('bank')
.required()
.messages({
'any.required': 'Template type is required',
}),
});
const updateTokenSchema = Joi.object({
notes: Joi.string()
.max(1000)
.allow(null, '')
.optional(),
});
const validate = (schema) => {
return (req, res, next) => {
const { error } = schema.validate(req.body, { abortEarly: false });
if (error) {
return res.status(400).json({
success: false,
error: 'Validation error',
details: error.details.map(d => d.message),
});
}
next();
};
};
module.exports = {
validateCreateToken: validate(createTokenSchema),
validateUpdateToken: validate(updateTokenSchema),
};