From 33aadc8c1d68c48dfffac4dacd72c9addadb2072 Mon Sep 17 00:00:00 2001 From: Eric Reber Date: Mon, 4 May 2026 11:02:48 +0200 Subject: [PATCH] enable ssl for pg connection --- server.js | 470 ++++++++++++++++++++++++++---------------------------- 1 file changed, 230 insertions(+), 240 deletions(-) diff --git a/server.js b/server.js index 8e9f382..4d19b1c 100644 --- a/server.js +++ b/server.js @@ -15,320 +15,310 @@ app.use(express.json({ limit: '10mb' })); // PostgreSQL connection pool function handleHeaders(headers) { + const alias = (headers['db-alias'] || 'default').toUpperCase().replace(/-/g, '_'); - const alias = (headers['db-alias'] || 'default').toUpperCase().replace(/-/g, '_'); + let pool = { + host: process.env[`DB_${alias}_HOST`], + port: process.env[`DB_${alias}_PORT`], + database: process.env[`DB_${alias}_DATABASE`], + user: process.env[`DB_${alias}_USER`], + password: process.env[`DB_${alias}_PASSWORD`], + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 2000, + }; - let pool={ - host: process.env[`DB_${alias}_HOST`], - port: process.env[`DB_${alias}_PORT`], - database: process.env[`DB_${alias}_DATABASE`], - user: process.env[`DB_${alias}_USER`], - password: process.env[`DB_${alias}_PASSWORD`], - max: 20, - idleTimeoutMillis: 30000, - connectionTimeoutMillis: 2000, - }; + const allUndefined = + pool.host === undefined && pool.port === undefined && pool.database === undefined && pool.user === undefined && pool.password === undefined; + const someUndefined = pool.host === '' || pool.port === '' || pool.database === '' || pool.user === '' || pool.password === ''; + const someDefined = pool.host != undefined || pool.port != undefined || pool.database != undefined || pool.user != undefined || pool.password != undefined; - const allUndefined = pool.host=== undefined && pool.port=== undefined && pool.database=== undefined && pool.user=== undefined && pool.password=== undefined; - const someUndefined = pool.host=== '' || pool.port=== '' || pool.database=== '' || pool.user=== '' || pool.password=== ''; - const someDefined = pool.host != undefined || pool.port != undefined || pool.database != undefined || pool.user != undefined || pool.password != undefined; - - if (allUndefined) { - throw new Error('Invalid db alias'); + if (allUndefined) { + throw new Error('Invalid db alias'); + } else if (someUndefined && someDefined) { + console.log(pool); + if (pool.host === '') { + throw new Error('Host is not configured for the specified db alias'); } - else if(someUndefined && someDefined) { - console.log(pool); - if(pool.host === '') { - throw new Error('Host is not configured for the specified db alias'); - } - if(pool.port === '') { - throw new Error('Port is not configured for the specified db alias'); - } - if(pool.database === '') { - throw new Error('Database is not configured for the specified db alias'); - } - if(pool.user === '') { - throw new Error('User is not configured for the specified db alias'); - } - if(pool.password === '') { - throw new Error('Password is not configured for the specified db alias'); - } - + if (pool.port === '') { + throw new Error('Port is not configured for the specified db alias'); } - else{ - return new Pool({ - host: process.env[`DB_${alias}_HOST`], - port: process.env[`DB_${alias}_PORT`], - database: process.env[`DB_${alias}_DATABASE`], - user: process.env[`DB_${alias}_USER`], - password: process.env[`DB_${alias}_PASSWORD`], - max: 20, - idleTimeoutMillis: 30000, - connectionTimeoutMillis: 2000, - }); + if (pool.database === '') { + throw new Error('Database is not configured for the specified db alias'); } - - + if (pool.user === '') { + throw new Error('User is not configured for the specified db alias'); + } + if (pool.password === '') { + throw new Error('Password is not configured for the specified db alias'); + } + } else { + return new Pool({ + host: process.env[`DB_${alias}_HOST`], + port: process.env[`DB_${alias}_PORT`], + database: process.env[`DB_${alias}_DATABASE`], + user: process.env[`DB_${alias}_USER`], + password: process.env[`DB_${alias}_PASSWORD`], + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 2000, + ssl: { rejectUnauthorized: false }, + }); + } } // Health check endpoint app.get('/api/health', (req, res) => { - res.json({ - status: 'ok', - timestamp: new Date().toISOString(), - node_version: process.version - }); + res.json({ + status: 'ok', + timestamp: new Date().toISOString(), + node_version: process.version, + }); }); // SELECT query endpoint app.post('/api/postgres/select', async (req, res) => { - const { query, bindings = [] } = req.body; + const { query, bindings = [] } = req.body; - if (!query) { - return res.status(422).json({ - success: false, - error: 'Query is required' - }); - } + if (!query) { + return res.status(422).json({ + success: false, + error: 'Query is required', + }); + } - let pool; - try { - pool = handleHeaders(req.headers); - const result = await pool.query(query, bindings); + let pool; + try { + pool = handleHeaders(req.headers); + const result = await pool.query(query, bindings); - res.json({ - success: true, - data: result.rows, - count: result.rowCount - }); - } catch (error) { - console.error('SELECT Error:', error); - res.status(400).json({ - success: false, - error: error.message - }); - } finally { - if (pool) await pool.end(); - } + res.json({ + success: true, + data: result.rows, + count: result.rowCount, + }); + } catch (error) { + console.error('SELECT Error:', error); + res.status(400).json({ + success: false, + error: error.message, + }); + } finally { + if (pool) await pool.end(); + } }); // EXECUTE query endpoint (INSERT, UPDATE, DELETE) app.post('/api/postgres/execute', async (req, res) => { - const { query, bindings = [] } = req.body; + const { query, bindings = [] } = req.body; - if (!query) { - return res.status(422).json({ - success: false, - error: 'Query is required' - }); - } + if (!query) { + return res.status(422).json({ + success: false, + error: 'Query is required', + }); + } - let pool; - try { - pool = handleHeaders(req.headers); - const result = await pool.query(query, bindings); + let pool; + try { + pool = handleHeaders(req.headers); + const result = await pool.query(query, bindings); - res.json({ - success: true, - affected_rows: result.rowCount - }); - } catch (error) { - console.error('EXECUTE Error:', error); - res.status(400).json({ - success: false, - error: error.message - }); - } finally { - if (pool) await pool.end(); - } + res.json({ + success: true, + affected_rows: result.rowCount, + }); + } catch (error) { + console.error('EXECUTE Error:', error); + res.status(400).json({ + success: false, + error: error.message, + }); + } finally { + if (pool) await pool.end(); + } }); // TRANSACTION endpoint app.post('/api/postgres/transaction', async (req, res) => { - const { queries } = req.body; + const { queries } = req.body; - if (!queries || !Array.isArray(queries)) { - return res.status(422).json({ - success: false, - error: 'Queries array is required' - }); + if (!queries || !Array.isArray(queries)) { + return res.status(422).json({ + success: false, + error: 'Queries array is required', + }); + } + + let pool; + let client; + try { + pool = handleHeaders(req.headers); + client = await pool.connect(); + + await client.query('BEGIN'); + + const results = []; + for (const item of queries) { + const result = await client.query(item.query, item.bindings || []); + results.push({ + rowCount: result.rowCount, + success: true, + }); } - let pool; - let client; - try { - pool = handleHeaders(req.headers); - client = await pool.connect(); + await client.query('COMMIT'); - await client.query('BEGIN'); - - const results = []; - for (const item of queries) { - const result = await client.query(item.query, item.bindings || []); - results.push({ - rowCount: result.rowCount, - success: true - }); - } - - await client.query('COMMIT'); - - res.json({ - success: true, - results: results - }); - } catch (error) { - if (client) await client.query('ROLLBACK'); - console.error('TRANSACTION Error:', error); - res.status(400).json({ - success: false, - error: error.message - }); - } finally { - if (client) client.release(); - if (pool) await pool.end(); - } + res.json({ + success: true, + results: results, + }); + } catch (error) { + if (client) await client.query('ROLLBACK'); + console.error('TRANSACTION Error:', error); + res.status(400).json({ + success: false, + error: error.message, + }); + } finally { + if (client) client.release(); + if (pool) await pool.end(); + } }); // INSERT simplified endpoint app.post('/api/postgres/insert', async (req, res) => { - const { table, data } = req.body; + const { table, data } = req.body; - if (!table || !data) { - return res.status(422).json({ - success: false, - error: 'Table and data are required' - }); - } + if (!table || !data) { + return res.status(422).json({ + success: false, + error: 'Table and data are required', + }); + } - let pool; - try { - pool = handleHeaders(req.headers); - const columns = Object.keys(data); - const values = Object.values(data); - const placeholders = values.map((_, i) => `$${i + 1}`).join(', '); + let pool; + try { + pool = handleHeaders(req.headers); + const columns = Object.keys(data); + const values = Object.values(data); + const placeholders = values.map((_, i) => `$${i + 1}`).join(', '); - const query = ` - INSERT INTO "${table}" (${columns.map(c => `"${c}"`).join(', ')}) + const query = ` + INSERT INTO "${table}" (${columns.map((c) => `"${c}"`).join(', ')}) VALUES (${placeholders}) RETURNING * `; - const result = await pool.query(query, values); + const result = await pool.query(query, values); - res.json({ - success: true, - data: result.rows[0] - }); - } catch (error) { - console.error('INSERT Error:', error); - res.status(400).json({ - success: false, - error: error.message - }); - } finally { - if (pool) await pool.end(); - } + res.json({ + success: true, + data: result.rows[0], + }); + } catch (error) { + console.error('INSERT Error:', error); + res.status(400).json({ + success: false, + error: error.message, + }); + } finally { + if (pool) await pool.end(); + } }); // UPDATE simplified endpoint app.post('/api/postgres/update', async (req, res) => { - const { table, data, where } = req.body; + const { table, data, where } = req.body; - if (!table || !data || !where) { - return res.status(422).json({ - success: false, - error: 'Table, data and where are required' - }); - } + if (!table || !data || !where) { + return res.status(422).json({ + success: false, + error: 'Table, data and where are required', + }); + } - let pool; - try { - pool = handleHeaders(req.headers); - const setColumns = Object.keys(data); - const setValues = Object.values(data); - const whereColumns = Object.keys(where); - const whereValues = Object.values(where); + let pool; + try { + pool = handleHeaders(req.headers); + const setColumns = Object.keys(data); + const setValues = Object.values(data); + const whereColumns = Object.keys(where); + const whereValues = Object.values(where); - const setClause = setColumns - .map((col, i) => `"${col}" = $${i + 1}`) - .join(', '); + const setClause = setColumns.map((col, i) => `"${col}" = $${i + 1}`).join(', '); - const whereClause = whereColumns - .map((col, i) => `"${col}" = $${setValues.length + i + 1}`) - .join(' AND '); + const whereClause = whereColumns.map((col, i) => `"${col}" = $${setValues.length + i + 1}`).join(' AND '); - const query = ` + const query = ` UPDATE "${table}" SET ${setClause} WHERE ${whereClause} `; - const result = await pool.query(query, [...setValues, ...whereValues]); + const result = await pool.query(query, [...setValues, ...whereValues]); - res.json({ - success: true, - affected_rows: result.rowCount - }); - } catch (error) { - console.error('UPDATE Error:', error); - res.status(400).json({ - success: false, - error: error.message - }); - } finally { - if (pool) await pool.end(); - } + res.json({ + success: true, + affected_rows: result.rowCount, + }); + } catch (error) { + console.error('UPDATE Error:', error); + res.status(400).json({ + success: false, + error: error.message, + }); + } finally { + if (pool) await pool.end(); + } }); // DELETE simplified endpoint app.post('/api/postgres/delete', async (req, res) => { - const { table, where } = req.body; + const { table, where } = req.body; - if (!table || !where) { - return res.status(422).json({ - success: false, - error: 'Table and where are required' - }); - } + if (!table || !where) { + return res.status(422).json({ + success: false, + error: 'Table and where are required', + }); + } - let pool; - try { - pool = handleHeaders(req.headers); - const whereColumns = Object.keys(where); - const whereValues = Object.values(where); + let pool; + try { + pool = handleHeaders(req.headers); + const whereColumns = Object.keys(where); + const whereValues = Object.values(where); - const whereClause = whereColumns - .map((col, i) => `"${col}" = $${i + 1}`) - .join(' AND '); + const whereClause = whereColumns.map((col, i) => `"${col}" = $${i + 1}`).join(' AND '); - const query = `DELETE FROM "${table}" WHERE ${whereClause}`; + const query = `DELETE FROM "${table}" WHERE ${whereClause}`; - const result = await pool.query(query, whereValues); + const result = await pool.query(query, whereValues); - res.json({ - success: true, - affected_rows: result.rowCount - }); - } catch (error) { - console.error('DELETE Error:', error); - res.status(400).json({ - success: false, - error: error.message - }); - } finally { - if (pool) await pool.end(); - } + res.json({ + success: true, + affected_rows: result.rowCount, + }); + } catch (error) { + console.error('DELETE Error:', error); + res.status(400).json({ + success: false, + error: error.message, + }); + } finally { + if (pool) await pool.end(); + } }); // Start server app.listen(PORT, () => { - console.log(`✓ Postgres API running on http://localhost:${PORT}`); - console.log(`✓ Health check: http://localhost:${PORT}/api/health`); + console.log(`✓ Postgres API running on http://localhost:${PORT}`); + console.log(`✓ Health check: http://localhost:${PORT}/api/health`); }); // Handle shutdown gracefully process.on('SIGINT', async () => { - console.log('\nShutting down gracefully...'); - process.exit(0); -}); \ No newline at end of file + console.log('\nShutting down gracefully...'); + process.exit(0); +});