webupdatev1

This commit is contained in:
Local Server
2026-01-04 17:52:37 -06:00
parent 1919f6f8bb
commit c1da8eff42
81 changed files with 16728 additions and 475 deletions

View File

@@ -1,21 +1,48 @@
const { query } = require("../config/database");
// Whitelist of allowed table names to prevent SQL injection
const ALLOWED_TABLES = [
"products",
"product_images",
"portfolioprojects",
"blogposts",
"pages",
"adminusers",
"roles",
"uploads",
"media_folders",
"team_members",
"site_settings",
"session",
];
// Validate table name against whitelist
const validateTableName = (table) => {
if (!ALLOWED_TABLES.includes(table)) {
throw new Error(`Invalid table name: ${table}`);
}
return table;
};
const buildSelectQuery = (
table,
conditions = [],
orderBy = "createdat DESC"
) => {
validateTableName(table);
const whereClause =
conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
return `SELECT * FROM ${table} ${whereClause} ORDER BY ${orderBy}`;
};
const getById = async (table, id) => {
validateTableName(table);
const result = await query(`SELECT * FROM ${table} WHERE id = $1`, [id]);
return result.rows[0] || null;
};
const getAllActive = async (table, orderBy = "createdat DESC") => {
validateTableName(table);
const result = await query(
`SELECT * FROM ${table} WHERE isactive = true ORDER BY ${orderBy}`
);
@@ -23,6 +50,7 @@ const getAllActive = async (table, orderBy = "createdat DESC") => {
};
const deleteById = async (table, id) => {
validateTableName(table);
const result = await query(
`DELETE FROM ${table} WHERE id = $1 RETURNING id`,
[id]
@@ -31,6 +59,7 @@ const deleteById = async (table, id) => {
};
const countRecords = async (table, condition = "") => {
validateTableName(table);
const whereClause = condition ? `WHERE ${condition}` : "";
const result = await query(`SELECT COUNT(*) FROM ${table} ${whereClause}`);
return parseInt(result.rows[0].count);
@@ -42,4 +71,5 @@ module.exports = {
getAllActive,
deleteById,
countRecords,
validateTableName,
};

View File

@@ -0,0 +1,111 @@
/**
* Sanitization utilities for user input
* Prevents XSS attacks by escaping HTML special characters
*/
/**
* Escape HTML special characters to prevent XSS
* @param {string} str - String to escape
* @returns {string} Escaped string
*/
const escapeHtml = (str) => {
if (typeof str !== "string") {
return str;
}
const htmlEscapeMap = {
"&": "&",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#x27;",
"/": "&#x2F;",
};
return str.replace(/[&<>"'/]/g, (char) => htmlEscapeMap[char]);
};
/**
* Sanitize object by escaping all string values
* @param {Object} obj - Object to sanitize
* @returns {Object} Sanitized object
*/
const sanitizeObject = (obj) => {
if (typeof obj !== "object" || obj === null) {
return obj;
}
const sanitized = {};
for (const [key, value] of Object.entries(obj)) {
if (typeof value === "string") {
sanitized[key] = escapeHtml(value);
} else if (typeof value === "object" && value !== null) {
sanitized[key] = sanitizeObject(value);
} else {
sanitized[key] = value;
}
}
return sanitized;
};
/**
* Strip all HTML tags from a string
* @param {string} str - String to strip
* @returns {string} String without HTML tags
*/
const stripHtml = (str) => {
if (typeof str !== "string") {
return str;
}
return str.replace(/<[^>]*>/g, "");
};
/**
* Validate and sanitize URL
* @param {string} url - URL to validate
* @returns {string|null} Sanitized URL or null if invalid
*/
const sanitizeUrl = (url) => {
if (typeof url !== "string") {
return null;
}
try {
const parsed = new URL(url);
// Only allow http and https protocols
if (!["http:", "https:"].includes(parsed.protocol)) {
return null;
}
return parsed.toString();
} catch {
return null;
}
};
/**
* Sanitize filename for safe storage
* @param {string} filename - Filename to sanitize
* @returns {string} Sanitized filename
*/
const sanitizeFilename = (filename) => {
if (typeof filename !== "string") {
return "file";
}
// Remove path separators and null bytes
return filename
.replace(/[\/\\]/g, "")
.replace(/\0/g, "")
.replace(/[^a-zA-Z0-9._-]/g, "-")
.substring(0, 255);
};
module.exports = {
escapeHtml,
sanitizeObject,
stripHtml,
sanitizeUrl,
sanitizeFilename,
};