Handballbooking/server/utils/initDatabase.js
2025-06-04 15:13:40 +02:00

231 lines
No EOL
7.7 KiB
JavaScript
Executable file

import mariadb from 'mariadb';
// import dotenv from 'dotenv'; // Remove dotenv
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// dotenv.config(); // Remove dotenv config
// Create a pool using hardcoded database credentials (LESS SECURE)
const initialPool = mariadb.createPool({
host: '172.10.1.4',
user: 'handball',
password: 'Gabi2104@',
database: 'handball',
connectionLimit: 5
});
// Ensure required directories exist
const ensureDirectories = () => {
const uploadsDir = path.join(__dirname, '..', '..', 'public', 'uploads');
const pdfDir = path.join(__dirname, '..', '..', 'public', 'pdfs');
// Create uploads directory if it doesn't exist
if (!fs.existsSync(uploadsDir)) {
fs.mkdirSync(uploadsDir, { recursive: true });
console.log('Created uploads directory');
}
// Create pdfs directory if it doesn't exist
if (!fs.existsSync(pdfDir)) {
fs.mkdirSync(pdfDir, { recursive: true });
console.log('Created pdfs directory');
}
};
// Ensure .env file exists with required variables (This check is no longer strictly necessary but can be kept as a reminder)
const ensureEnvFile = () => {
const envPath = path.join(__dirname, '..' , '.env');
const requiredEnvVars = [
'DB_HOST',
'DB_USER',
'DB_PASSWORD',
'DB_NAME',
'PORT',
'SMTP_HOST',
'SMTP_PORT',
'SMTP_USER',
'SMTP_PASS'
];
if (!fs.existsSync(envPath)) {
console.warn('Warning: .env file not found. Using hardcoded credentials.'); // Change to warning
// Do not throw error, just warn
} else {
const envContent = fs.readFileSync(envPath, 'utf8');
const missingVars = requiredEnvVars.filter(varName => !envContent.includes(`${varName}=`)); // Check for key=value
if (missingVars.length > 0) {
console.warn('Warning: Missing required environment variables in .env:', missingVars.join(', ')); // Change to warning
}
}
};
// List of all required tables and their creation SQL
const tableDefinitions = {
matches: `
CREATE TABLE matches (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
date DATETIME NOT NULL,
location VARCHAR(255) NOT NULL,
totalSeats INT NOT NULL,
availableSeats INT NOT NULL,
price DECIMAL(10,2) DEFAULT 0,
timeoutDate DATETIME NOT NULL,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`,
tickets: `
CREATE TABLE tickets (
id INT AUTO_INCREMENT PRIMARY KEY,
matchId INT NOT NULL,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(20) NOT NULL,
seats INT NOT NULL,
status ENUM('pending', 'confirmed', 'cancelled') DEFAULT 'pending',
pdfFile VARCHAR(255),
deliveryMethod ENUM('download', 'email') DEFAULT 'download',
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_ticket_match FOREIGN KEY (matchId) REFERENCES matches(id) ON DELETE CASCADE
) /* Added ON DELETE CASCADE */
`,
seats: `
CREATE TABLE seats (
id INT AUTO_INCREMENT PRIMARY KEY,
matchId INT NOT NULL,
seatNumber INT NOT NULL,
status ENUM('available', 'reserved', 'booked') DEFAULT 'available',
ticketId INT NULL,
direction VARCHAR(50),
extractedSeatNumber INT,
uploadedPdfPath VARCHAR(255),
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_seat_match FOREIGN KEY (matchId) REFERENCES matches(id) ON DELETE CASCADE, /* Added ON DELETE CASCADE */
CONSTRAINT fk_seat_ticket FOREIGN KEY (ticketId) REFERENCES tickets(id) ON DELETE SET NULL, /* Added ON DELETE SET NULL */
UNIQUE KEY unique_seat_match (matchId, seatNumber)
)
`,
admin: `
CREATE TABLE admin (
id INT AUTO_INCREMENT PRIMARY KEY,
passwordHash VARCHAR(255) NOT NULL,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) /* No foreign keys */
`,
admin_settings: `
CREATE TABLE admin_settings (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(255) NOT NULL UNIQUE,
setting_value TEXT,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) /* No foreign keys */
`
};
// Check if table exists
const tableExists = async (conn, tableName) => {
try {
const result = await conn.query(
`SELECT COUNT(*) as count FROM information_schema.tables
WHERE table_schema = ? AND table_name = ?`, // Use env var for schema
[process.env.DB_NAME, tableName]
);
return result[0].count > 0;
} catch (error) {
console.error(`Error checking if table ${tableName} exists:`, error);
return false;
}
};
// Create all tables
const createTables = async (conn) => {
try {
// Create tables in correct order to satisfy foreign keys
const orderedTableNames = ['matches', 'tickets', 'seats', 'admin', 'admin_settings'];
for (const tableName of orderedTableNames) {
const createSQL = tableDefinitions[tableName];
if (!createSQL) {
console.error(`Error: Table definition for ${tableName} not found.`);
continue;
}
try {
console.log(`Creating ${tableName} table...`);
await conn.query(createSQL);
console.log(`${tableName} table created successfully`);
} catch (error) {
// If table already exists, that's fine - just log it
if (error.code === 'ER_TABLE_EXISTS_ERROR') {
console.log(`${tableName} table already exists, skipping creation`);
} else {
// For any other error, rethrow it
throw error;
}
}
}
} catch (error) {
console.error('Error creating tables:', error);
throw error;
}
};
// Export the initialPool (Keep this export)
export { initialPool };
async function initDatabase() {
try {
// Check required directories and files
ensureDirectories();
ensureEnvFile(); // Keep the check but it won't stop execution
console.log('Attempting to connect to database server using hardcoded credentials...'); // Updated log
let conn;
try {
// Connect directly to the database using hardcoded credentials
conn = await initialPool.getConnection();
console.log('Connected to database server.');
// Check if the database exists (Keep this logic)
const dbCheck = await conn.query(
`SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?`,
['handball'] // Use hardcoded DB name here
);
if (dbCheck.length === 0) {
console.log(`Database 'handball' not found. Creating...`); // Updated log
// Create the database
await conn.query(`CREATE DATABASE handball`); // Use hardcoded DB name here
console.log(`Database 'handball' created.`); // Updated log
} else {
console.log(`Database 'handball' already exists.`); // Updated log
}
// Now that the database exists, ensure the connection is using it
// (Initial pool is already configured with hardcoded DB name)
console.log('Attempting to create tables (if they don\'t exist)...');
// Create tables if they don't exist
await createTables(conn);
console.log('Database initialization completed successfully');
} catch (error) {
console.error('Error during database initialization:', error);
throw error;
} finally {
if (conn) conn.release();
// The pool created with hardcoded DB name is needed for the main server
console.log('Database initialization complete, pool kept open for server using hardcoded credentials.'); // Updated log
}
} catch (error) {
console.error('Startup checks failed:', error);
throw error;
}
}
export default initDatabase;