AI.Demo/server/database.js

188 lines
5.2 KiB
JavaScript

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 };