Add password generator, Caprover deployment, and position as modern legacy tool replacement

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-08 01:37:58 +00:00
parent e4ec2b7d18
commit 684d8cd73c
6 changed files with 334 additions and 15 deletions

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env node
import * as crypto from 'node:crypto';
/**
* Generate a secure random password
* @param length - Length of the password (default: 32)
* @param includeSpecial - Include special characters (default: true)
*/
function generateSecurePassword(length = 32, includeSpecial = true): string {
let charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
if (includeSpecial) {
charset += '!@#$%^&*()-_=+[]{}|;:,.<>?';
}
const randomBytes = crypto.randomBytes(length);
let password = '';
for (let i = 0; i < length; i++) {
const byte = randomBytes[i];
if (byte !== undefined) {
password += charset[byte % charset.length];
}
}
return password;
}
// CLI interface
if (require.main === module) {
const args = process.argv.slice(2);
const length = args[0] ? Number.parseInt(args[0], 10) : 32;
const includeSpecial = args[1] !== 'false';
if (Number.isNaN(length) || length < 8) {
console.error('Error: Password length must be at least 8 characters');
process.exit(1);
}
if (length > 128) {
console.error('Error: Password length cannot exceed 128 characters');
process.exit(1);
}
const password = generateSecurePassword(length, includeSpecial);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🔐 Secure Password Generated');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(`Password: ${password}`);
console.log(`Length: ${password.length} characters`);
console.log(`Special characters: ${includeSpecial ? 'Yes' : 'No'}`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('⚠️ Save this password securely!');
console.log('');
console.log('💡 Usage examples:');
console.log(` ADMIN_PASSWORD="${password}" npm run db:seed-admin`);
console.log(` export JWT_SECRET="${password}"`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
}
export { generateSecurePassword };

View File

@@ -2,6 +2,7 @@ import * as bcrypt from 'bcryptjs';
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
import { adminUserSchema } from '../src/models/Schema';
import { generateSecurePassword } from './generate-password';
async function seedAdminUser() {
const pool = new Pool({
@@ -11,7 +12,15 @@ async function seedAdminUser() {
const db = drizzle(pool);
const username = process.env.ADMIN_USERNAME || 'admin';
const password = process.env.ADMIN_PASSWORD || 'admin123';
// Generate secure password if not provided
let password = process.env.ADMIN_PASSWORD;
let passwordGenerated = false;
if (!password) {
password = generateSecurePassword(32);
passwordGenerated = true;
}
const passwordHash = await bcrypt.hash(password, 10);
@@ -21,14 +30,20 @@ async function seedAdminUser() {
passwordHash,
});
console.log(`Admin user created successfully!`);
console.log(`Username: ${username}`);
console.log(`Password: ${password}`);
console.log('✅ Admin user created successfully!');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(`📧 Username: ${username}`);
console.log(`🔑 Password: ${password}`);
if (passwordGenerated) {
console.log('⚠️ This password was auto-generated. Save it securely!');
}
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🌐 Login at: http://localhost:3000/admin/login');
} catch (error: any) {
if (error.code === '23505') {
console.log('Admin user already exists');
console.log(' Admin user already exists');
} else {
console.error('Error creating admin user:', error);
console.error('Error creating admin user:', error);
}
} finally {
await pool.end();