fix: verify password type

This commit is contained in:
shinya
2025-07-28 12:53:18 +08:00
parent 8f03bbfde4
commit 67b6132780
4 changed files with 43 additions and 20 deletions

View File

@@ -1 +1 @@
20250728105125
20250728125318

View File

@@ -8,6 +8,15 @@ import { Favorite, IStorage, PlayRecord } from './types';
// 搜索历史最大条数
const SEARCH_HISTORY_LIMIT = 20;
// 数据类型转换辅助函数
function ensureString(value: any): string {
return String(value);
}
function ensureStringArray(value: any[]): string[] {
return value.map((item) => String(item));
}
// 添加Redis操作重试包装器
async function withRetry<T>(
operation: () => Promise<T>,
@@ -99,7 +108,7 @@ export class RedisStorage implements IStorage {
if (raw) {
const rec = JSON.parse(raw) as PlayRecord;
// 截取 source+id 部分
const keyPart = fullKey.replace(`u:${userName}:pr:`, '');
const keyPart = ensureString(fullKey.replace(`u:${userName}:pr:`, ''));
result[keyPart] = rec;
}
});
@@ -142,7 +151,7 @@ export class RedisStorage implements IStorage {
const raw = values[idx];
if (raw) {
const fav = JSON.parse(raw) as Favorite;
const keyPart = fullKey.replace(`u:${userName}:fav:`, '');
const keyPart = ensureString(fullKey.replace(`u:${userName}:fav:`, ''));
result[keyPart] = fav;
}
});
@@ -168,7 +177,8 @@ export class RedisStorage implements IStorage {
this.client.get(this.userPwdKey(userName))
);
if (stored === null) return false;
return stored === password;
// 确保比较时都是字符串类型
return ensureString(stored) === password;
}
// 检查用户是否存在
@@ -221,17 +231,19 @@ export class RedisStorage implements IStorage {
}
async getSearchHistory(userName: string): Promise<string[]> {
return withRetry(
() => this.client.lRange(this.shKey(userName), 0, -1) as Promise<string[]>
const result = await withRetry(() =>
this.client.lRange(this.shKey(userName), 0, -1)
);
// 确保返回的都是字符串类型
return ensureStringArray(result as any[]);
}
async addSearchHistory(userName: string, keyword: string): Promise<void> {
const key = this.shKey(userName);
// 先去重
await withRetry(() => this.client.lRem(key, 0, keyword));
await withRetry(() => this.client.lRem(key, 0, ensureString(keyword)));
// 插入到最前
await withRetry(() => this.client.lPush(key, keyword));
await withRetry(() => this.client.lPush(key, ensureString(keyword)));
// 限制最大长度
await withRetry(() => this.client.lTrim(key, 0, SEARCH_HISTORY_LIMIT - 1));
}
@@ -239,7 +251,7 @@ export class RedisStorage implements IStorage {
async deleteSearchHistory(userName: string, keyword?: string): Promise<void> {
const key = this.shKey(userName);
if (keyword) {
await withRetry(() => this.client.lRem(key, 0, keyword));
await withRetry(() => this.client.lRem(key, 0, ensureString(keyword)));
} else {
await withRetry(() => this.client.del(key));
}
@@ -251,7 +263,7 @@ export class RedisStorage implements IStorage {
return keys
.map((k) => {
const match = k.match(/^u:(.+?):pwd$/);
return match ? match[1] : undefined;
return match ? ensureString(match[1]) : undefined;
})
.filter((u): u is string => typeof u === 'string');
}

View File

@@ -8,6 +8,15 @@ import { Favorite, IStorage, PlayRecord } from './types';
// 搜索历史最大条数
const SEARCH_HISTORY_LIMIT = 20;
// 数据类型转换辅助函数
function ensureString(value: any): string {
return String(value);
}
function ensureStringArray(value: any[]): string[] {
return value.map((item) => String(item));
}
// 添加Upstash Redis操作重试包装器
async function withRetry<T>(
operation: () => Promise<T>,
@@ -86,7 +95,7 @@ export class UpstashRedisStorage implements IStorage {
const value = await withRetry(() => this.client.get(fullKey));
if (value) {
// 截取 source+id 部分
const keyPart = fullKey.replace(`u:${userName}:pr:`, '');
const keyPart = ensureString(fullKey.replace(`u:${userName}:pr:`, ''));
result[keyPart] = value as PlayRecord;
}
}
@@ -128,7 +137,7 @@ export class UpstashRedisStorage implements IStorage {
for (const fullKey of keys) {
const value = await withRetry(() => this.client.get(fullKey));
if (value) {
const keyPart = fullKey.replace(`u:${userName}:fav:`, '');
const keyPart = ensureString(fullKey.replace(`u:${userName}:fav:`, ''));
result[keyPart] = value as Favorite;
}
}
@@ -154,7 +163,8 @@ export class UpstashRedisStorage implements IStorage {
this.client.get(this.userPwdKey(userName))
);
if (stored === null) return false;
return stored === password;
// 确保比较时都是字符串类型
return ensureString(stored) === password;
}
// 检查用户是否存在
@@ -210,15 +220,16 @@ export class UpstashRedisStorage implements IStorage {
const result = await withRetry(() =>
this.client.lrange(this.shKey(userName), 0, -1)
);
return result as string[];
// 确保返回的都是字符串类型
return ensureStringArray(result as any[]);
}
async addSearchHistory(userName: string, keyword: string): Promise<void> {
const key = this.shKey(userName);
// 先去重
await withRetry(() => this.client.lrem(key, 0, keyword));
await withRetry(() => this.client.lrem(key, 0, ensureString(keyword)));
// 插入到最前
await withRetry(() => this.client.lpush(key, keyword));
await withRetry(() => this.client.lpush(key, ensureString(keyword)));
// 限制最大长度
await withRetry(() => this.client.ltrim(key, 0, SEARCH_HISTORY_LIMIT - 1));
}
@@ -226,7 +237,7 @@ export class UpstashRedisStorage implements IStorage {
async deleteSearchHistory(userName: string, keyword?: string): Promise<void> {
const key = this.shKey(userName);
if (keyword) {
await withRetry(() => this.client.lrem(key, 0, keyword));
await withRetry(() => this.client.lrem(key, 0, ensureString(keyword)));
} else {
await withRetry(() => this.client.del(key));
}
@@ -238,7 +249,7 @@ export class UpstashRedisStorage implements IStorage {
return keys
.map((k) => {
const match = k.match(/^u:(.+?):pwd$/);
return match ? match[1] : undefined;
return match ? ensureString(match[1]) : undefined;
})
.filter((u): u is string => typeof u === 'string');
}
@@ -269,7 +280,7 @@ function getUpstashRedisClient(): Redis {
if (!upstashUrl || !upstashToken) {
throw new Error(
'UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN env variables must be set'
'UPSTASH_URL and UPSTASH_TOKEN env variables must be set'
);
}

View File

@@ -2,7 +2,7 @@
'use client';
const CURRENT_VERSION = '20250728105125';
const CURRENT_VERSION = '20250728125318';
// 版本检查结果枚举
export enum UpdateStatus {