Skip to content

Commit

Permalink
seguridad en server Cross-Site Scripting (XSS)-
Browse files Browse the repository at this point in the history
  • Loading branch information
RyuDSora committed Jul 29, 2024
1 parent f96ca80 commit 949cc97
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 12 deletions.
14 changes: 8 additions & 6 deletions server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import classRoute from './routes/classRoute.js';
import paymentRoute from './routes/paymentRoute.js';
import ratingRoute from './routes/ratingRoute.js';
import tutorsubjectRoute from './routes/tutorsubjectRoute.js';
import chatRoutes from './routes/chatRoutes.js'; // Importar el router de chat
import chatRoutes from './routes/chatRoutes.js';

const app = express();
const port = process.env.PORT || 3000; // Usar variable de entorno para el puerto
const port = process.env.PORT || 3000;

// Configura CORS
app.use(cors({
origin: ['https://tu-torias.vercel.app', 'http://localhost:5173'],
methods: ['GET', 'POST', 'PUT','PATCH','DELETE'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
credentials: true,
}));

Expand All @@ -38,7 +38,7 @@ app.use('/classes', classRoute);
app.use('/payments', paymentRoute);
app.use('/ratings', ratingRoute);
app.use('/ts', tutorsubjectRoute);
app.use('/api', chatRoutes); // Usar las rutas de chat
app.use('/api', chatRoutes);

app.get('/', (req, res) => {
res.status(200).json('Bienvenido, tu aplicación se ha ejecutado correctamente');
Expand All @@ -55,7 +55,6 @@ const io = new Server(server, {
},
});


const connectedUsers = new Map();

io.on('connection', (socket) => {
Expand All @@ -81,12 +80,15 @@ io.on('connection', (socket) => {
});
});

server.listen(port, () => {});
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});

app.get('/test', (req, res) => {
res.status(200).send('Server is running');
});


/*
const db = require('./utils/database');
Expand Down
184 changes: 180 additions & 4 deletions server/controllers/tableController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,181 @@
import pool from '../database/db.js';
import escapeHtml from 'escape-html';

// Crear una tabla con columnas y claves foráneas opcionales
export const createTable = async (req, res) => {
const { tableName, columns, foreignKeys } = req.body;
const client = await pool.connect();

try {
// Construir la definición de la tabla con columna 'id' como llave primaria
const createTableQuery = `
CREATE TABLE IF NOT EXISTS ${tableName} (
id SERIAL PRIMARY KEY,
${columns.map(column => {
const length = column.length ? `(${column.length})` : '';
return `${column.name} ${column.type}${length}`;
}).join(', ')}
)
`;
await client.query(createTableQuery);

// Agregar claves foráneas si existen
if (foreignKeys && foreignKeys.length > 0) {
for (const fk of foreignKeys) {
const addForeignKeyQuery = `
ALTER TABLE ${tableName}
ADD CONSTRAINT fk_${fk.column}
FOREIGN KEY (${fk.column})
REFERENCES ${fk.references.table}(${fk.references.column})
`;
await client.query(addForeignKeyQuery);
}
}

res.status(201).send(`Table ${tableName} created successfully.`);
} catch (error) {
console.error('Error creating table:', error);
res.status(500).send('Error creating table.');
} finally {
client.release();
}
};



// Verificar si una tabla existe
export const checkTableExists = async (req, res) => {
const { tableName } = req.params;
const client = await pool.connect();
try {
if (!tableName) {
return res.status(400).send('Table name is required.');
}

const checkTableQuery = `
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = $1
);
`;
const result = await client.query(checkTableQuery, [tableName]);
if (result.rows[0].exists) {
res.send(`Table ${tableName} exists.`);
} else {
res.send(`Table ${tableName} does not exist.`);
}
} catch (error) {
console.error('Error checking table existence:', error);
res.status(500).send('Error checking table existence.');
} finally {
client.release();
}
};

// Obtener todos los nombres de las tablas con sus columnas y llaves primarias
export const getAllTables = async (req, res) => {
const client = await pool.connect();
try {
const getTablesQuery = `
SELECT
c.table_name,
c.column_name,
c.data_type,
c.is_nullable,
tc.constraint_type
FROM
information_schema.columns c
LEFT JOIN information_schema.key_column_usage kcu
ON c.table_name = kcu.table_name
AND c.column_name = kcu.column_name
LEFT JOIN information_schema.table_constraints tc
ON kcu.constraint_name = tc.constraint_name
AND tc.constraint_type = 'PRIMARY KEY'
WHERE
c.table_schema = 'public'
ORDER BY
c.table_name, c.ordinal_position;
`;
const result = await client.query(getTablesQuery);
const tables = {};

result.rows.forEach(row => {
if (!tables[row.table_name]) {
tables[row.table_name] = { columns: [] };
}
tables[row.table_name].columns.push({
column_name: row.column_name,
data_type: row.data_type,
is_nullable: row.is_nullable,
is_primary_key: row.constraint_type === 'PRIMARY KEY'
});
});

res.json(tables);
} catch (error) {
console.error('Error fetching table names and columns:', error);
res.status(500).send('Error fetching table names and columns.');
} finally {
client.release();
}
};
// Eliminar una tabla
export const dropTable = async (req, res) => {
const { tableName } = req.params;
const client = await pool.connect();
try {
if (!tableName) {
return res.status(400).send('Table name is required.');
}

const dropTableQuery = `DROP TABLE IF EXISTS ${tableName};`;
await client.query(dropTableQuery);
res.send(`Table ${tableName} has been dropped if it existed.`);
} catch (error) {
console.error('Error dropping table:', error);
res.status(500).send('Error dropping table.');
} finally {
client.release();
}
};

// Actualizar una tabla (agregar/eliminar columnas)
export const updateTable = async (req, res) => {
const { tableName } = req.params;
const { addColumns, dropColumns } = req.body;
const client = await pool.connect();
try {
if (!tableName) {
return res.status(400).send('Table name is required.');
}

let alterTableQuery = `ALTER TABLE ${tableName}`;

if (addColumns && addColumns.length > 0) {
const addColumnsDef = addColumns.map(col => `ADD COLUMN ${col.name} ${col.type}`).join(', ');
alterTableQuery += ` ${addColumnsDef}`;
}

if (dropColumns && dropColumns.length > 0) {
if (addColumns && addColumns.length > 0) {
alterTableQuery += ',';
}
const dropColumnsDef = dropColumns.map(col => `DROP COLUMN ${col}`).join(', ');
alterTableQuery += ` ${dropColumnsDef}`;
}

alterTableQuery += ';';

await client.query(alterTableQuery);
res.send(`Table ${tableName} has been updated.`);
} catch (error) {
console.error('Error updating table:', error);
res.status(500).send('Error updating table.');
} finally {
client.release();
}
};

// Obtener todas las tablas y sus columnas
export const getTablesAndColumns = async (req, res) => {
const client = await pool.connect();
Expand All @@ -11,7 +187,7 @@ export const getTablesAndColumns = async (req, res) => {
ORDER BY table_name;
`;
const tablesResult = await client.query(tablesQuery);
const tables = tablesResult.rows.map(row => escapeHtml(row.table_name));
const tables = tablesResult.rows.map(row => row.table_name);

const tablesAndColumns = {};

Expand All @@ -22,7 +198,7 @@ export const getTablesAndColumns = async (req, res) => {
WHERE table_name = $1;
`;
const columnsResult = await client.query(columnsQuery, [table]);
tablesAndColumns[table] = columnsResult.rows.map(row => escapeHtml(row.column_name));
tablesAndColumns[table] = columnsResult.rows.map(row => row.column_name);
}

res.json(tablesAndColumns);
Expand All @@ -32,4 +208,4 @@ export const getTablesAndColumns = async (req, res) => {
} finally {
client.release();
}
};
};
22 changes: 20 additions & 2 deletions server/routes/tableRoute.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
import express from 'express';
import {getAllTables} from '../controllers/tableController.js';
import { createTable, checkTableExists, getAllTables, dropTable, updateTable,getTablesAndColumns } from '../controllers/tableController.js';
import rateLimit from 'express-rate-limit';

const router = express.Router();

// Configura el limitador de velocidad para rutas sensibles
const sensitiveRouteLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutos
max: 50, // máximo 50 solicitudes por ventana de tiempo
message: 'Too many requests from this IP, please try again after 15 minutes' // mensaje de error personalizado
});

// Configura el limitador de velocidad general (si decides usarlo)
const generalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutos
max: 100, // máximo 100 solicitudes por ventana de tiempo
message: 'Too many requests from this IP, please try again after 15 minutes' // mensaje de error personalizado
});

// Ruta para crear una tabla con columnas definidas en el cuerpo de la solicitud
router.post('/create-table', sensitiveRouteLimiter,createTable);

// Ruta para verificar si una tabla existe
router.get('/check-table/:tableName', generalLimiter, checkTableExists);

// Ruta para obtener todos los nombres de las tablas
router.get('/get-tables', generalLimiter,getAllTables);

// Ruta para eliminar una tabla
router.delete('/drop-table/:tableName',sensitiveRouteLimiter, dropTable);

// Ruta para actualizar una tabla
router.put('/update-table/:tableName',sensitiveRouteLimiter, updateTable);

router.get('/get-tables-columns',generalLimiter, getTablesAndColumns);

export default router;

0 comments on commit 949cc97

Please sign in to comment.