用户数据结构变更
This commit is contained in:
+192
-1
@@ -132,7 +132,7 @@ export class DbManager {
|
||||
return favorite !== null;
|
||||
}
|
||||
|
||||
// ---------- 用户相关 ----------
|
||||
// ---------- 用户相关(旧版本,保持兼容) ----------
|
||||
async registerUser(userName: string, password: string): Promise<void> {
|
||||
await this.storage.registerUser(userName, password);
|
||||
}
|
||||
@@ -154,6 +154,197 @@ export class DbManager {
|
||||
await this.storage.deleteUser(userName);
|
||||
}
|
||||
|
||||
// ---------- 用户相关(新版本) ----------
|
||||
async createUserV2(
|
||||
userName: string,
|
||||
password: string,
|
||||
role: 'owner' | 'admin' | 'user' = 'user',
|
||||
tags?: string[],
|
||||
oidcSub?: string,
|
||||
enabledApis?: string[]
|
||||
): Promise<void> {
|
||||
if (typeof (this.storage as any).createUserV2 === 'function') {
|
||||
await (this.storage as any).createUserV2(userName, password, role, tags, oidcSub, enabledApis);
|
||||
}
|
||||
}
|
||||
|
||||
async verifyUserV2(userName: string, password: string): Promise<boolean> {
|
||||
if (typeof (this.storage as any).verifyUserV2 === 'function') {
|
||||
return (this.storage as any).verifyUserV2(userName, password);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async getUserInfoV2(userName: string): Promise<{
|
||||
role: 'owner' | 'admin' | 'user';
|
||||
banned: boolean;
|
||||
tags?: string[];
|
||||
oidcSub?: string;
|
||||
enabledApis?: string[];
|
||||
created_at: number;
|
||||
} | null> {
|
||||
if (typeof (this.storage as any).getUserInfoV2 === 'function') {
|
||||
return (this.storage as any).getUserInfoV2(userName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async updateUserInfoV2(
|
||||
userName: string,
|
||||
updates: {
|
||||
role?: 'owner' | 'admin' | 'user';
|
||||
banned?: boolean;
|
||||
tags?: string[];
|
||||
oidcSub?: string;
|
||||
enabledApis?: string[];
|
||||
}
|
||||
): Promise<void> {
|
||||
if (typeof (this.storage as any).updateUserInfoV2 === 'function') {
|
||||
await (this.storage as any).updateUserInfoV2(userName, updates);
|
||||
}
|
||||
}
|
||||
|
||||
async changePasswordV2(userName: string, newPassword: string): Promise<void> {
|
||||
if (typeof (this.storage as any).changePasswordV2 === 'function') {
|
||||
await (this.storage as any).changePasswordV2(userName, newPassword);
|
||||
}
|
||||
}
|
||||
|
||||
async checkUserExistV2(userName: string): Promise<boolean> {
|
||||
if (typeof (this.storage as any).checkUserExistV2 === 'function') {
|
||||
return (this.storage as any).checkUserExistV2(userName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async getUserByOidcSub(oidcSub: string): Promise<string | null> {
|
||||
if (typeof (this.storage as any).getUserByOidcSub === 'function') {
|
||||
return (this.storage as any).getUserByOidcSub(oidcSub);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async getUserListV2(
|
||||
offset: number = 0,
|
||||
limit: number = 20,
|
||||
ownerUsername?: string
|
||||
): Promise<{
|
||||
users: Array<{
|
||||
username: string;
|
||||
role: 'owner' | 'admin' | 'user';
|
||||
banned: boolean;
|
||||
tags?: string[];
|
||||
enabledApis?: string[];
|
||||
created_at: number;
|
||||
}>;
|
||||
total: number;
|
||||
}> {
|
||||
if (typeof (this.storage as any).getUserListV2 === 'function') {
|
||||
return (this.storage as any).getUserListV2(offset, limit, ownerUsername);
|
||||
}
|
||||
return { users: [], total: 0 };
|
||||
}
|
||||
|
||||
async deleteUserV2(userName: string): Promise<void> {
|
||||
if (typeof (this.storage as any).deleteUserV2 === 'function') {
|
||||
await (this.storage as any).deleteUserV2(userName);
|
||||
}
|
||||
}
|
||||
|
||||
async getUsersByTag(tagName: string): Promise<string[]> {
|
||||
if (typeof (this.storage as any).getUsersByTag === 'function') {
|
||||
return (this.storage as any).getUsersByTag(tagName);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
// ---------- 数据迁移 ----------
|
||||
async migrateUsersFromConfig(adminConfig: AdminConfig): Promise<void> {
|
||||
if (typeof (this.storage as any).createUserV2 !== 'function') {
|
||||
throw new Error('当前存储类型不支持新版用户存储');
|
||||
}
|
||||
|
||||
const users = adminConfig.UserConfig.Users;
|
||||
if (!users || users.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`开始迁移 ${users.length} 个用户...`);
|
||||
|
||||
for (const user of users) {
|
||||
try {
|
||||
// 跳过站长(站长使用环境变量认证,不需要迁移)
|
||||
if (user.role === 'owner') {
|
||||
console.log(`跳过站长 ${user.username} 的迁移`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查用户是否已经迁移
|
||||
const exists = await this.checkUserExistV2(user.username);
|
||||
if (exists) {
|
||||
console.log(`用户 ${user.username} 已存在,跳过迁移`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取密码
|
||||
let password = '';
|
||||
|
||||
// 如果是OIDC用户,生成随机密码(OIDC用户不需要密码登录)
|
||||
if ((user as any).oidcSub) {
|
||||
password = crypto.randomUUID();
|
||||
console.log(`用户 ${user.username} (OIDC用户) 使用随机密码迁移`);
|
||||
}
|
||||
// 如果是站长,使用环境变量中的密码
|
||||
else if (user.username === process.env.USERNAME && process.env.PASSWORD) {
|
||||
password = process.env.PASSWORD;
|
||||
console.log(`用户 ${user.username} (站长) 使用环境变量密码迁移`);
|
||||
}
|
||||
// 尝试从旧的存储中获取密码
|
||||
else {
|
||||
try {
|
||||
if ((this.storage as any).client) {
|
||||
const storedPassword = await (this.storage as any).client.get(`u:${user.username}:pwd`);
|
||||
if (storedPassword) {
|
||||
password = storedPassword;
|
||||
console.log(`用户 ${user.username} 使用旧密码迁移`);
|
||||
} else {
|
||||
// 没有旧密码,使用默认密码
|
||||
password = 'defaultPassword123';
|
||||
console.log(`用户 ${user.username} 没有旧密码,使用默认密码`);
|
||||
}
|
||||
} else {
|
||||
password = 'defaultPassword123';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`获取用户 ${user.username} 的密码失败,使用默认密码`, err);
|
||||
password = 'defaultPassword123';
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新用户
|
||||
await this.createUserV2(
|
||||
user.username,
|
||||
password,
|
||||
user.role,
|
||||
user.tags,
|
||||
(user as any).oidcSub,
|
||||
user.enabledApis
|
||||
);
|
||||
|
||||
// 如果用户被封禁,更新状态
|
||||
if (user.banned) {
|
||||
await this.updateUserInfoV2(user.username, { banned: true });
|
||||
}
|
||||
|
||||
console.log(`用户 ${user.username} 迁移成功`);
|
||||
} catch (err) {
|
||||
console.error(`迁移用户 ${user.username} 失败:`, err);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('用户迁移完成');
|
||||
}
|
||||
|
||||
// ---------- 搜索历史 ----------
|
||||
async getSearchHistory(userName: string): Promise<string[]> {
|
||||
return this.storage.getSearchHistory(userName);
|
||||
|
||||
Reference in New Issue
Block a user