修复导入用户丢失问题
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
204.0.0
|
205.0.0
|
||||||
@@ -165,11 +165,8 @@ export async function POST(req: NextRequest) {
|
|||||||
const userData = importData.data.userData;
|
const userData = importData.data.userData;
|
||||||
for (const username in userData) {
|
for (const username in userData) {
|
||||||
const user = userData[username];
|
const user = userData[username];
|
||||||
|
await db.createUserV2(username, user.password,user.role,user.tags);
|
||||||
// 重新注册用户(包含密码)- 仅用于旧版用户
|
|
||||||
if (user.password && !importData.data.usersV2?.find((u: any) => u.username === username)) {
|
|
||||||
await db.registerUser(username, user.password);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导入播放记录
|
// 导入播放记录
|
||||||
if (user.playRecords) {
|
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({
|
return NextResponse.json({
|
||||||
|
|||||||
@@ -165,9 +165,6 @@ export async function POST(request: NextRequest) {
|
|||||||
// 使用新版本创建用户
|
// 使用新版本创建用户
|
||||||
await db.createUserV2(targetUsername!, targetPassword, 'user', tags);
|
await db.createUserV2(targetUsername!, targetPassword, 'user', tags);
|
||||||
|
|
||||||
// 同时在旧版本存储中创建(保持兼容性)
|
|
||||||
await db.registerUser(targetUsername!, targetPassword);
|
|
||||||
|
|
||||||
// 不再更新配置,因为用户已经存储在新版本中
|
// 不再更新配置,因为用户已经存储在新版本中
|
||||||
// 构造一个虚拟的targetEntry用于后续逻辑
|
// 构造一个虚拟的targetEntry用于后续逻辑
|
||||||
targetEntry = {
|
targetEntry = {
|
||||||
@@ -298,8 +295,6 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
// 使用新版本修改密码(SHA256加密)
|
// 使用新版本修改密码(SHA256加密)
|
||||||
await db.changePasswordV2(targetUsername!, targetPassword);
|
await db.changePasswordV2(targetUsername!, targetPassword);
|
||||||
// 同时更新旧版本(保持兼容性)
|
|
||||||
await db.changePassword(targetUsername!, targetPassword);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'deleteUser': {
|
case 'deleteUser': {
|
||||||
@@ -327,8 +322,6 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
// 只删除V2存储中的用户
|
// 只删除V2存储中的用户
|
||||||
await db.deleteUserV2(targetUsername!);
|
await db.deleteUserV2(targetUsername!);
|
||||||
// 同时删除旧版本(保持兼容性)
|
|
||||||
await db.deleteUser(targetUsername!);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
users,
|
users: [],
|
||||||
total,
|
total: 0,
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
totalPages: Math.ceil(total / limit),
|
totalPages: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -124,10 +124,6 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
// 检查用户名是否已存在(优先使用新版本)
|
// 检查用户名是否已存在(优先使用新版本)
|
||||||
let userExists = await db.checkUserExistV2(username);
|
let userExists = await db.checkUserExistV2(username);
|
||||||
if (!userExists) {
|
|
||||||
// 回退到旧版本检查
|
|
||||||
userExists = await db.checkUserExist(username);
|
|
||||||
}
|
|
||||||
if (userExists) {
|
if (userExists) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: '用户名已存在' },
|
{ error: '用户名已存在' },
|
||||||
|
|||||||
@@ -231,19 +231,6 @@ export async function POST(req: NextRequest) {
|
|||||||
pass = await db.verifyUserV2(username, password);
|
pass = await db.verifyUserV2(username, password);
|
||||||
userRole = userInfoV2.role;
|
userRole = userInfoV2.role;
|
||||||
isBanned = userInfoV2.banned;
|
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 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查用户是否被封禁
|
// 检查用户是否被封禁
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ export default function AIChatPanel({
|
|||||||
</p>
|
</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'>
|
<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}
|
{message.content}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-5
@@ -132,11 +132,7 @@ export class DbManager {
|
|||||||
return favorite !== null;
|
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> {
|
async verifyUser(userName: string, password: string): Promise<boolean> {
|
||||||
return this.storage.verifyUser(userName, password);
|
return this.storage.verifyUser(userName, password);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,11 +492,6 @@ export abstract class BaseRedisStorage implements IStorage {
|
|||||||
return `u:${user}:pwd`;
|
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> {
|
async verifyUser(userName: string, password: string): Promise<boolean> {
|
||||||
const stored = await this.withRetry(() =>
|
const stored = await this.withRetry(() =>
|
||||||
this.client.get(this.userPwdKey(userName))
|
this.client.get(this.userPwdKey(userName))
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ export interface IStorage {
|
|||||||
migrateFavorites(userName: string): Promise<void>;
|
migrateFavorites(userName: string): Promise<void>;
|
||||||
|
|
||||||
// 用户相关
|
// 用户相关
|
||||||
registerUser(userName: string, password: string): Promise<void>;
|
|
||||||
verifyUser(userName: string, password: string): Promise<boolean>;
|
verifyUser(userName: string, password: string): Promise<boolean>;
|
||||||
// 检查用户是否存在(无需密码)
|
// 检查用户是否存在(无需密码)
|
||||||
checkUserExist(userName: string): Promise<boolean>;
|
checkUserExist(userName: string): Promise<boolean>;
|
||||||
|
|||||||
@@ -393,11 +393,6 @@ export class UpstashRedisStorage implements IStorage {
|
|||||||
return `u:${user}:pwd`;
|
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> {
|
async verifyUser(userName: string, password: string): Promise<boolean> {
|
||||||
const stored = await withRetry(() =>
|
const stored = await withRetry(() =>
|
||||||
this.client.get(this.userPwdKey(userName))
|
this.client.get(this.userPwdKey(userName))
|
||||||
|
|||||||
Reference in New Issue
Block a user