mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
fix: 统一管理员密码管理机制,以init.json为唯一数据源
- app.js: 每次启动强制从init.json加载管理员凭据到Redis,确保数据一致性 - web.js: 修改密码时先更新init.json,成功后再更新Redis缓存 - cli/index.js: CLI创建管理员时同时更新init.json和Redis - setup.js: 优化提示信息,明确重置密码需要重启服务 - admin.js: 修复Claude账户专属绑定功能的验证逻辑 解决了之前存在的双重存储同步问题,现在init.json是唯一真实数据源。 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
57
src/app.js
57
src/app.js
@@ -183,40 +183,37 @@ class Application {
|
||||
}
|
||||
}
|
||||
|
||||
// 🔧 初始化管理员凭据
|
||||
// 🔧 初始化管理员凭据(总是从 init.json 加载,确保数据一致性)
|
||||
async initializeAdmin() {
|
||||
try {
|
||||
// 检查Redis中是否已存在管理员凭据
|
||||
const existingAdmin = await redis.getSession('admin_credentials');
|
||||
const initFilePath = path.join(__dirname, '..', 'data', 'init.json');
|
||||
|
||||
if (!existingAdmin || Object.keys(existingAdmin).length === 0) {
|
||||
// 尝试从初始化文件读取
|
||||
const initFilePath = path.join(__dirname, '..', 'data', 'init.json');
|
||||
|
||||
if (fs.existsSync(initFilePath)) {
|
||||
const initData = JSON.parse(fs.readFileSync(initFilePath, 'utf8'));
|
||||
|
||||
// 将明文密码哈希化
|
||||
const saltRounds = 10;
|
||||
const passwordHash = await bcrypt.hash(initData.adminPassword, saltRounds);
|
||||
|
||||
// 存储到Redis
|
||||
const adminCredentials = {
|
||||
username: initData.adminUsername,
|
||||
passwordHash: passwordHash,
|
||||
createdAt: new Date().toISOString(),
|
||||
lastLogin: null
|
||||
};
|
||||
|
||||
await redis.setSession('admin_credentials', adminCredentials);
|
||||
|
||||
logger.success('✅ Admin credentials initialized from setup data');
|
||||
} else {
|
||||
logger.warn('⚠️ No admin credentials found. Please run npm run setup first.');
|
||||
}
|
||||
} else {
|
||||
logger.info('ℹ️ Admin credentials already exist in Redis');
|
||||
if (!fs.existsSync(initFilePath)) {
|
||||
logger.warn('⚠️ No admin credentials found. Please run npm run setup first.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 从 init.json 读取管理员凭据(作为唯一真实数据源)
|
||||
const initData = JSON.parse(fs.readFileSync(initFilePath, 'utf8'));
|
||||
|
||||
// 将明文密码哈希化
|
||||
const saltRounds = 10;
|
||||
const passwordHash = await bcrypt.hash(initData.adminPassword, saltRounds);
|
||||
|
||||
// 存储到Redis(每次启动都覆盖,确保与 init.json 同步)
|
||||
const adminCredentials = {
|
||||
username: initData.adminUsername,
|
||||
passwordHash: passwordHash,
|
||||
createdAt: initData.initializedAt || new Date().toISOString(),
|
||||
lastLogin: null,
|
||||
updatedAt: initData.updatedAt || null
|
||||
};
|
||||
|
||||
await redis.setSession('admin_credentials', adminCredentials);
|
||||
|
||||
logger.success('✅ Admin credentials loaded from init.json (single source of truth)');
|
||||
logger.info(`📋 Admin username: ${adminCredentials.username}`);
|
||||
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to initialize admin credentials:', { error: error.message, stack: error.stack });
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user