Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validation fix #1979

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,253 changes: 735 additions & 518 deletions index.html

Large diffs are not rendered by default.

109 changes: 97 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,108 @@ document.addEventListener("DOMContentLoaded", function () {
const errorMessage = document.getElementById("error-message");
const subscribeButton = document.getElementById("subscribe-button");

subscribeButton.addEventListener("click", function (event) {
event.preventDefault();
// Email validation function
function isValidEmail(email) {
if (!email || typeof email !== "string") return false;
if (email.length > 254) return false;

// Split email into local part and domain
const parts = email.split("@");
if (parts.length !== 2) return false;
const [localPart, domain] = parts;

// Local part validation
if (!isValidLocalPart(localPart)) return false;

// Domain validation
if (!isValidDomain(domain)) return false;

return true;
}

function isValidLocalPart(localPart) {
if (!localPart || localPart.length > 64) return false;
if (localPart.startsWith(".") || localPart.endsWith(".")) return false;
if (localPart.includes("..")) return false;

// Allowed characters check
const validLocalRegex = /^[a-zA-Z0-9!#$%&'*+\-/=?^_`{|}~.]+$/;
return validLocalRegex.test(localPart);
}

function isValidDomain(domain) {
if (!domain || domain.length > 255) return false;
if (domain.startsWith(".") || domain.endsWith(".")) return false;
if (domain.includes("..")) return false;

// Split domain into parts
const parts = domain.split(".");
if (parts.length < 2) return false;

// Check each part
for (const part of parts) {
if (!part || part.length > 63) return false;
if (part.startsWith("-") || part.endsWith("-")) return false;

const validDomainRegex = /^[a-zA-Z0-9-]+$/;
if (!validDomainRegex.test(part)) return false;
}

// TLD should only contain letters
const tld = parts[parts.length - 1];
if (!/^[a-zA-Z]{2,}$/.test(tld)) return false;

return true;
}

if (emailInput.value.trim() === "") {
alert("Email address is required.");
} else if (!isValidEmail(emailInput.value)) {
alert("Invalid email address format.");
// Function to display error message
function showError(message) {
if (errorMessage) {
errorMessage.textContent = message;
errorMessage.style.display = "block";
emailInput.classList.add("error");
} else {
form.submit();
alert(message);
}
});
}

function isValidEmail(email) {
// Regular expression for email validation
const emailRegex = /^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
return emailRegex.test(email);
function clearError() {
if (errorMessage) {
errorMessage.style.display = "none";
emailInput.classList.remove("error");
}
}

// Real-time validation as user types
emailInput?.addEventListener("input", function () {
const email = this.value.trim();
if (email === "") {
clearError();
} else if (!isValidEmail(email)) {
showError("Please enter a valid email address");
} else {
clearError();
}
});

subscribeButton?.addEventListener("click", function (event) {
event.preventDefault();
const email = emailInput.value.trim();

if (email === "") {
showError("Email address is required.");
return;
}

if (!isValidEmail(email)) {
showError("Please enter a valid email address.");
return;
}

// If all validation passes, submit the form, for now added these checks
clearError();
form.submit();
});
});

// scroll to top function
Expand Down
39 changes: 23 additions & 16 deletions navbar.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,44 @@
const navBar = document.getElementById("navbar");
const logo = document.getElementById("logo");
const navBtn = document.getElementById("nav-button");
const hamburgerIcon = document.getElementById("hamburger-icon");
const closeIcon = document.getElementById("close-icon");

let prevScrollPos = window.pageYOffset
let prevScrollPos = window.pageYOffset;
let isNavExpanded = false;

navBtn.addEventListener("click", () => {
isNavExpanded = !isNavExpanded;
navBar.classList.toggle("hidden");
logo.classList.toggle("hidden");
navBtn.setAttribute("aria-expanded", isNavExpanded);

// Toggle between hamburger and X icons
hamburgerIcon.classList.toggle("hidden");
closeIcon.classList.toggle("hidden");
});

window.onscroll = function() {
myFunction()
let currentScrollPos = window.pageYOffset
toggleNavBar(currentScrollPos > prevScrollPos, currentScrollPos)
window.onscroll = function () {
myFunction();
let currentScrollPos = window.pageYOffset;
toggleNavBar(currentScrollPos > prevScrollPos, currentScrollPos);
};

var header = document.getElementById("header");
// var sticky = header.offsetTop;

function myFunction() {
if (window.pageYOffset > 10) {
header.classList.add("add_border");
}
else {
} else {
header.classList.remove("add_border");
}
}
function toggleNavBar(scrollDir, currPos){
prevScrollPos=currPos
if(scrollDir){
header.classList.add('nav-hidden')
}
else{
header.classList.remove('nav-hidden')
}

function toggleNavBar(scrollDir, currPos) {
prevScrollPos = currPos;
if (scrollDir) {
header.classList.add("nav-hidden");
} else {
header.classList.remove("nav-hidden");
}
}
42 changes: 24 additions & 18 deletions server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const dotenv = require('dotenv');

const petRouter = require('./routes/petRoutes');
const donationRouter = require('./routes/donationRoutes');
const strayAnimalReportRouter = require('./routes/strayAnimalReportRoutes')
const strayAnimalReportRouter = require('./routes/strayAnimalReportRoutes');
const AppError = require('./utils/appError');
const errorController = require('./controllers/errorController');

Expand All @@ -20,34 +20,36 @@ dotenv.config({ path: './config.env' }); // <- connecting the enviroment variabl
// MIDLEWARES ->>
app.enable('trust proxy');

console.log('REMOTE: ', process.env.REMOTE);
console.log('REMOTE: ', process.env.REMOTE || 'http://localhost');

app.use(cors({ credentials: true, origin: process.env.REMOTE })); // <- CORS configuration, in case if you wanted to implemented authorization
app.options(process.env.REMOTE, cors());

console.log((`ENV = ${process.env.NODE_ENV}`));
console.log(`ENV = ${process.env.NODE_ENV}`);
app.use(morgan('dev')); // <- Logs res status code and time taken

const limiter = rateLimit({ // <- Limits the number of api calls that can be made per IP address
max: 1000, // max number of times per windowMS
windowMs: 60 * 60 * 1000,
message:
const limiter = rateLimit({
// <- Limits the number of api calls that can be made per IP address
max: 1000, // max number of times per windowMS
windowMs: 60 * 60 * 1000,
message:
'!!! Too many requests from this IP, Please try again in 1 hour !!!',
});

app.use('/api/v1', limiter);

app.use((req, res, next) => { // <- Serves req time and cookies

req.requestTime = new Date().toISOString();
console.log(req.requestTime);
if (req.cookies) console.log(req.cookies);
next();
app.use((req, res, next) => {
// <- Serves req time and cookies

req.requestTime = new Date().toISOString();
console.log(req.requestTime);
if (req.cookies) console.log(req.cookies);
next();
});

app.use((req, res, next) => {
res.setHeader('Content-Type', 'application/json');
next();
res.setHeader('Content-Type', 'application/json');
next();
});

app.use(express.json({ limit: '100mb' })); // <- Parses Json data
Expand All @@ -59,14 +61,18 @@ app.use(xss()); // <- Data Sanitization against xss
app.use(compression());

// routs for images
app.use('/api/v1/AnimalReportImage',express.static('public/Images/RportedAnimals'))
app.use(
'/api/v1/AnimalReportImage',
express.static('public/Images/RportedAnimals')
);

app.use('/api/v1/pet', petRouter); // <- Calling the router
app.use('/api/v1/donation', donationRouter);
app.use('/api/v1/reportAnimal', strayAnimalReportRouter);

app.all('*', (req, res, next) => { // <- Middleware to handle Non-existing Routes
next(new AppError(`Can't find ${req.originalUrl} on the server`, 404));
app.all('*', (req, res, next) => {
// <- Middleware to handle Non-existing Routes
next(new AppError(`Can't find ${req.originalUrl} on the server`, 404));
});

app.use(errorController); // <- Error Handling Middleware
Expand Down
15 changes: 8 additions & 7 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"multer": "^1.4.5-lts.1",
"promisify": "0.0.3",
"util": "^0.12.4",
"validator": "^13.7.0",
"validator": "^13.12.0",
"xss-clean": "^0.1.1"
}
}
73 changes: 36 additions & 37 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,48 @@ const app = require('./app');
// Below snippet is used to connect to DB. This is disablled becouse we will not be needing Database for this project

// Connecting to DATABASE ->>
const DB = process.env.DATABASE.replace(
'<PASSWORD>',
process.env.DATABASE_PASSWORD
);

mongoose
.connect(DB, {
// <- Using Mongoose Connection
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
})
.then(() => {
console.log('DB connection established');
})
.catch((err) => {
console.log('DB CONNECTION FAILED');
console.log('ERR: ', err);
});

// Catching uncaught exception ->>
process.on('unCaughtException', (err) => {
console.log(`UNCAUGHT EXCEPTION -> ${err.name} - ${err.message}`);
console.log('App SHUTTING DOWN...');
process.exit(1); // <- Then will shut down the server.
});
// const DB = process.env.DATABASE.replace(
// '<PASSWORD>',
// process.env.DATABASE_PASSWORD
// );

// mongoose
// .connect(DB, {
// // <- Using Mongoose Connection
// useNewUrlParser: true,
// useCreateIndex: true,
// useFindAndModify: false,
// useUnifiedTopology: true,
// })
// .then(() => {
// console.log('DB connection established');
// })
// .catch((err) => {
// console.log('DB CONNECTION FAILED');
// console.log('ERR: ', err);
// });

// // Catching uncaught exception ->>
// process.on('unCaughtException', (err) => {
// console.log(`UNCAUGHT EXCEPTION -> ${err.name} - ${err.message}`);
// console.log('App SHUTTING DOWN...');
// process.exit(1); // <- Then will shut down the server.
// });

// Starting Server ->>
const port = process.env.PORT || 8000;
const server = app.listen(port, () => {
console.log(`App running at port`, (`${port}`), '...');
console.log(`App running at port`, `${port}`, '...');
});


// Catching unHandleled Rejections ->
process.on('unhandledRejection', (err) => {
console.log(`UNHANDELLED REJECTION -> ${err.name} - ${err.message}`);
console.log(err);
console.log('App SHUTTING DOWN...');
server.close(() => { // <- This will first terminate all requests

process.exit(1); // <- Then will shut down the server.
});
console.log(`UNHANDELLED REJECTION -> ${err.name} - ${err.message}`);
console.log(err);
console.log('App SHUTTING DOWN...');
server.close(() => {
// <- This will first terminate all requests

process.exit(1); // <- Then will shut down the server.
});
});

Loading