import initSqlJs from 'sql.js'; import bcrypt from 'bcryptjs'; import path from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); // 数据库文件路径 const dbPath = process.env.DATABASE_PATH || path.join(__dirname, 'data', 'auth.db'); const dbDir = path.dirname(dbPath); // 确保数据目录存在 if (!fs.existsSync(dbDir)) { fs.mkdirSync(dbDir, { recursive: true }); } let db = null; // 初始化数据库 async function initDatabase() { const SQL = await initSqlJs(); // 尝试加载现有数据库文件 if (fs.existsSync(dbPath)) { const fileBuffer = fs.readFileSync(dbPath); db = new SQL.Database(fileBuffer); } else { db = new SQL.Database(); } // 创建表 db.run(` CREATE TABLE IF NOT EXISTS access_passwords ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); db.run(` CREATE TABLE IF NOT EXISTS admin_users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // 初始化默认管理员账户 const adminUsername = process.env.ADMIN_USERNAME || 'admin'; const adminPassword = process.env.ADMIN_PASSWORD || 'admin123456'; const existingAdmin = db.exec('SELECT id FROM admin_users WHERE username = ?', [adminUsername]); if (existingAdmin.length === 0 || existingAdmin[0].values.length === 0) { const passwordHash = bcrypt.hashSync(adminPassword, 10); db.run('INSERT INTO admin_users (username, password_hash) VALUES (?, ?)', [adminUsername, passwordHash]); console.log(`[DB] 默认管理员账户已创建: ${adminUsername}`); } // 保存数据库 saveDatabase(); } // 保存数据库到文件 function saveDatabase() { if (db) { const data = db.export(); const buffer = Buffer.from(data); fs.writeFileSync(dbPath, buffer); } } // ── 访问密码操作 ── export function getAllPasswords() { const result = db.exec('SELECT id, name, created_at FROM access_passwords ORDER BY created_at DESC'); if (result.length === 0) return []; const columns = result[0].columns; return result[0].values.map(row => { const obj = {}; columns.forEach((col, i) => { obj[col] = row[i]; }); return obj; }); } export function getPasswordByName(name) { const result = db.exec('SELECT * FROM access_passwords WHERE name = ?', [name]); if (result.length === 0 || result[0].values.length === 0) return null; const columns = result[0].columns; const row = result[0].values[0]; const obj = {}; columns.forEach((col, i) => { obj[col] = row[i]; }); return obj; } export function addPassword(name, password) { const passwordHash = bcrypt.hashSync(password, 10); try { db.run('INSERT INTO access_passwords (name, password_hash) VALUES (?, ?)', [name, passwordHash]); saveDatabase(); // 获取最后插入的 ID const idResult = db.exec('SELECT last_insert_rowid()'); const id = idResult[0].values[0][0]; return { success: true, id }; } catch (error) { if (error.message && error.message.includes('UNIQUE constraint failed')) { return { success: false, error: '密码名称已存在' }; } throw error; } } export function deletePassword(id) { db.run('DELETE FROM access_passwords WHERE id = ?', [id]); saveDatabase(); // 检查是否删除了记录 const result = db.exec('SELECT changes()'); return result[0].values[0][0] > 0; } export function verifyPassword(name, password) { // 如果只提供密码,遍历所有密码记录进行匹配 if (!name && password) { const allPasswords = getAllPasswords(); for (const record of allPasswords) { const fullRecord = getPasswordByName(record.name); if (fullRecord && bcrypt.compareSync(password, fullRecord.password_hash)) { return { valid: true, name: record.name }; } } return false; } // 如果提供了名称和密码,按名称验证 const record = getPasswordByName(name); if (!record) { return false; } return bcrypt.compareSync(password, record.password_hash) ? { valid: true, name } : false; } // ── 管理员操作 ── export function getAdminByUsername(username) { const result = db.exec('SELECT * FROM admin_users WHERE username = ?', [username]); if (result.length === 0 || result[0].values.length === 0) return null; const columns = result[0].columns; const row = result[0].values[0]; const obj = {}; columns.forEach((col, i) => { obj[col] = row[i]; }); return obj; } export function verifyAdminPassword(username, password) { const admin = getAdminByUsername(username); if (!admin) { return false; } return bcrypt.compareSync(password, admin.password_hash); } export function updateAdminPassword(username, newPassword) { const passwordHash = bcrypt.hashSync(newPassword, 10); db.run('UPDATE admin_users SET password_hash = ? WHERE username = ?', [passwordHash, username]); saveDatabase(); const result = db.exec('SELECT changes()'); return result[0].values[0][0] > 0; } // 导出初始化函数 export { initDatabase };