From 2279e619288115c4ffd8f2bd9572e8257df7712e Mon Sep 17 00:00:00 2001 From: Grant Fitzsimmons <37256050+grantfitzsimmons@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:12:17 -0500 Subject: [PATCH] Update clone.ts --- app/pages/api/databases/[name]/clone.ts | 65 ++++++++++--------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/app/pages/api/databases/[name]/clone.ts b/app/pages/api/databases/[name]/clone.ts index f35b0d0..e9a6402 100644 --- a/app/pages/api/databases/[name]/clone.ts +++ b/app/pages/api/databases/[name]/clone.ts @@ -18,52 +18,38 @@ export default async function handler( const user = await getUser(request, res); if (typeof user === 'undefined') return; - await connectToDatabase(); + const connection = await connectToDatabase(); - const databaseName = Array.isArray(request.query.name) ? request.query.name[0] : request.query.name; + // Define the existing database name to clone + const existingDatabaseName = request.query.name as string | undefined; - if (!databaseName) { - return res.status(400).json({ error: 'Database name is required.' }); + if (!existingDatabaseName) { + return res.status(400).json({ error: 'Existing database name is required' }); } - const timestamp = new Date().toISOString().replace(/T/, '_').replace(/:/g, '_').split('.')[0]; - const newDatabaseName = `${databaseName}_${timestamp}`; + // Validate that the existing database name is valid + if (existingDatabaseName.match(/^\w+$/) === null) { + return res.status(400).json({ error: 'Existing database name is invalid' }); + } try { - // Create the new database - const createDatabaseChild = spawn( - 'mysql', - [ - `-u${process.env.MYSQL_USERNAME}`, - `-p${process.env.MYSQL_PASSWORD}`, - `-h${process.env.MYSQL_HOST}`, - '-e', - `CREATE DATABASE ${newDatabaseName};`, - ], - { - stdio: 'inherit', - shell: true, - } - ); + // Generate a new database name with timestamp + const timestamp = new Date().toISOString().replace(/T/, '_').replace(/:/g, '_').split('.')[0]; + const newDatabaseName = `${existingDatabaseName}_${timestamp}`; - await new Promise((resolve, reject) => { - createDatabaseChild.on('exit', (code) => { - if (code !== 0) { - return reject(new Error(`Failed to create database: ${newDatabaseName}`)); - } - resolve(null); - }); - }); + // Create the new database + await connection.execute(`DROP DATABASE IF EXISTS \`${newDatabaseName}\``); + await connection.execute(`CREATE DATABASE \`${newDatabaseName}\``); - // Clone the current database into the new database - const cloneDatabaseChild = spawn( + // Clone the existing database into the new database + const cloneChild = spawn( 'mysqldump', [ `-u${process.env.MYSQL_USERNAME}`, `-p${process.env.MYSQL_PASSWORD}`, `-h${process.env.MYSQL_HOST}`, '--databases', - databaseName, + existingDatabaseName, '--no-create-db', ], { @@ -87,9 +73,10 @@ export default async function handler( ); // Pipe the dump output to the new database - cloneDatabaseChild.stdout.pipe(importChild.stdin); - cloneDatabaseChild.stderr.on('data', (error) => { - throw new Error(error); + cloneChild.stdout.pipe(importChild.stdin); + cloneChild.stderr.on('data', (error) => { + console.error('Error cloning database:', error.toString()); + throw new Error(`Failed to clone database from ${existingDatabaseName} to ${newDatabaseName}`); }); await new Promise((resolve, reject) => { @@ -104,9 +91,7 @@ export default async function handler( res.status(200).json({ message: `Database cloned successfully: ${newDatabaseName}`, }); - } catch (error) { - res.status(500).json({ - error: (error as Error).message, - }); + } catch (error: any) { + res.status(500).json({ error: error.toString() }); } -} \ No newline at end of file +}