In this final step, we'll explore advanced techniques to prevent bad input and enhance data integrity in MongoDB through comprehensive validation strategies.
Preparing the Environment
Let's continue in our MongoDB shell:
mongosh
Switch to our existing database:
use dataValidationLab
Creating a Robust Validation Schema
We'll create a comprehensive validation schema for a 'registrations' collection:
db.createCollection("registrations", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["username", "email", "password", "registrationDate"],
properties: {
username: {
bsonType: "string",
minLength: 3,
maxLength: 20,
pattern: "^[a-zA-Z0-9_]+$",
description: "Username must be alphanumeric, 3-20 characters"
},
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
description: "Must be a valid email address"
},
password: {
bsonType: "string",
minLength: 8,
description: "Password must be at least 8 characters",
pattern:
"^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$"
},
registrationDate: {
bsonType: "date",
description: "Registration date must be a valid date"
}
}
}
},
validationAction: "error",
validationLevel: "strict"
});
Create a function to validate input before insertion:
function safeRegister(userData) {
// Sanitize and validate input
const sanitizedData = {
username: userData.username.trim().toLowerCase(),
email: userData.email.trim().toLowerCase(),
password: userData.password,
registrationDate: new Date()
};
// Additional custom validations
if (sanitizedData.username.length < 3) {
throw new Error("Username too short");
}
if (db.registrations.findOne({ username: sanitizedData.username })) {
throw new Error("Username already exists");
}
if (db.registrations.findOne({ email: sanitizedData.email })) {
throw new Error("Email already registered");
}
try {
// Attempt to insert with MongoDB validation
db.registrations.insertOne(sanitizedData);
print("Registration successful:", sanitizedData.username);
} catch (error) {
print("Registration failed:", error.message);
// Log failed registration attempts
db.registrationAttempts.insertOne({
attemptData: userData,
errorMessage: error.message,
timestamp: new Date()
});
}
}
// Test input prevention
function testRegistrations() {
const testCases = [
// Valid registration
{
username: "john_doe",
email: "[email protected]",
password: "Strong!Pass123"
},
// Invalid cases
{ username: "ab", email: "invalid-email", password: "short" },
{ username: "john_doe!", email: "[email protected]", password: "WeakPass" },
{
username: "special_chars!",
email: "invalid@email",
password: "NoSpecialChar123"
}
];
testCases.forEach((testCase) => {
print("\nTesting registration:");
printjson(testCase);
safeRegister(testCase);
});
}
// Run registration tests
testRegistrations();
Reviewing Registration Attempts
Check the logged registration attempts:
print("Failed Registration Attempts:");
db.registrationAttempts.find();
- Use comprehensive schema validation
- Implement server-side input sanitization
- Use regex patterns for strict validation
- Log and track invalid input attempts
- Implement additional custom validation logic