修复导入用户丢失问题

This commit is contained in:
mtvpls
2025-12-31 23:27:15 +08:00
parent 52d84942ad
commit c2442d03a6
11 changed files with 8 additions and 80 deletions

View File

@@ -1 +1 @@
204.0.0
205.0.0

View File

@@ -165,11 +165,8 @@ export async function POST(req: NextRequest) {
const userData = importData.data.userData;
for (const username in userData) {
const user = userData[username];
// 重新注册用户(包含密码)- 仅用于旧版用户
if (user.password && !importData.data.usersV2?.find((u: any) => u.username === username)) {
await db.registerUser(username, user.password);
}
await db.createUserV2(username, user.password,user.role,user.tags);
// 导入播放记录
if (user.playRecords) {
@@ -201,13 +198,6 @@ export async function POST(req: NextRequest) {
}
}
}
// 标记播放记录已迁移新导入的数据直接使用hash结构
const storage = (db as any).storage;
if (storage && typeof storage.client?.hSet === 'function') {
const userInfoKey = `user:${username}:info`;
await storage.client.hSet(userInfoKey, 'playrecord_migrated', 'true');
}
}
return NextResponse.json({

View File

@@ -165,9 +165,6 @@ export async function POST(request: NextRequest) {
// 使用新版本创建用户
await db.createUserV2(targetUsername!, targetPassword, 'user', tags);
// 同时在旧版本存储中创建(保持兼容性)
await db.registerUser(targetUsername!, targetPassword);
// 不再更新配置,因为用户已经存储在新版本中
// 构造一个虚拟的targetEntry用于后续逻辑
targetEntry = {
@@ -298,8 +295,6 @@ export async function POST(request: NextRequest) {
// 使用新版本修改密码SHA256加密
await db.changePasswordV2(targetUsername!, targetPassword);
// 同时更新旧版本(保持兼容性)
await db.changePassword(targetUsername!, targetPassword);
break;
}
case 'deleteUser': {
@@ -327,8 +322,6 @@ export async function POST(request: NextRequest) {
// 只删除V2存储中的用户
await db.deleteUserV2(targetUsername!);
// 同时删除旧版本(保持兼容性)
await db.deleteUser(targetUsername!);
break;
}

View File

@@ -71,36 +71,13 @@ export async function GET(request: NextRequest) {
);
}
// 回退到配置中的用户列表
const configUsers = adminConfig.UserConfig.Users || [];
const total = configUsers.length;
// 排序:站长始终在第一位,其他用户按用户名排序
const sortedUsers = [...configUsers].sort((a, b) => {
if (a.username === process.env.USERNAME) return -1;
if (b.username === process.env.USERNAME) return 1;
return a.username.localeCompare(b.username);
});
// 分页
const paginatedUsers = sortedUsers.slice(offset, offset + limit);
// 转换为统一格式
const users = paginatedUsers.map((u) => ({
username: u.username,
role: u.role,
banned: u.banned || false,
tags: u.tags,
created_at: 0, // 配置中没有创建时间
}));
return NextResponse.json(
{
users,
total,
users: [],
total: 0,
page,
limit,
totalPages: Math.ceil(total / limit),
totalPages: 0,
},
{
headers: {

View File

@@ -124,10 +124,6 @@ export async function POST(request: NextRequest) {
// 检查用户名是否已存在(优先使用新版本)
let userExists = await db.checkUserExistV2(username);
if (!userExists) {
// 回退到旧版本检查
userExists = await db.checkUserExist(username);
}
if (userExists) {
return NextResponse.json(
{ error: '用户名已存在' },

View File

@@ -231,19 +231,6 @@ export async function POST(req: NextRequest) {
pass = await db.verifyUserV2(username, password);
userRole = userInfoV2.role;
isBanned = userInfoV2.banned;
} else {
// 回退到旧版本验证
try {
pass = await db.verifyUser(username, password);
// 从配置中获取角色和封禁状态
if (user) {
userRole = user.role;
isBanned = user.banned || false;
}
} catch (err) {
console.error('数据库验证失败', err);
return NextResponse.json({ error: '数据库错误' }, { status: 500 });
}
}
// 检查用户是否被封禁

View File

@@ -329,7 +329,7 @@ export default function AIChatPanel({
</p>
) : (
<div className='prose prose-sm max-w-none dark:prose-invert prose-p:my-2 prose-p:leading-relaxed prose-pre:bg-gray-800 prose-pre:text-gray-100 dark:prose-pre:bg-gray-900 prose-code:text-purple-600 dark:prose-code:text-purple-400 prose-code:bg-purple-50 dark:prose-code:bg-purple-900/20 prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:before:content-none prose-code:after:content-none prose-a:text-blue-600 dark:prose-a:text-blue-400 prose-strong:text-gray-900 dark:prose-strong:text-white prose-ul:my-2 prose-ol:my-2 prose-li:my-1'>
<ReactMarkdown remarkPlugins={[remarkGfm]}>
<ReactMarkdown remarkPlugins={[remarkGfm as any]}>
{message.content}
</ReactMarkdown>
</div>

View File

@@ -132,11 +132,7 @@ export class DbManager {
return favorite !== null;
}
// ---------- 用户相关(旧版本,保持兼容) ----------
async registerUser(userName: string, password: string): Promise<void> {
await this.storage.registerUser(userName, password);
}
async verifyUser(userName: string, password: string): Promise<boolean> {
return this.storage.verifyUser(userName, password);
}

View File

@@ -492,11 +492,6 @@ export abstract class BaseRedisStorage implements IStorage {
return `u:${user}:pwd`;
}
async registerUser(userName: string, password: string): Promise<void> {
// 简单存储明文密码,生产环境应加密
await this.withRetry(() => this.client.set(this.userPwdKey(userName), password));
}
async verifyUser(userName: string, password: string): Promise<boolean> {
const stored = await this.withRetry(() =>
this.client.get(this.userPwdKey(userName))

View File

@@ -53,7 +53,6 @@ export interface IStorage {
migrateFavorites(userName: string): Promise<void>;
// 用户相关
registerUser(userName: string, password: string): Promise<void>;
verifyUser(userName: string, password: string): Promise<boolean>;
// 检查用户是否存在(无需密码)
checkUserExist(userName: string): Promise<boolean>;

View File

@@ -393,11 +393,6 @@ export class UpstashRedisStorage implements IStorage {
return `u:${user}:pwd`;
}
async registerUser(userName: string, password: string): Promise<void> {
// 简单存储明文密码,生产环境应加密
await withRetry(() => this.client.set(this.userPwdKey(userName), password));
}
async verifyUser(userName: string, password: string): Promise<boolean> {
const stored = await withRetry(() =>
this.client.get(this.userPwdKey(userName))