merge dhk-1 yuser login cache
This commit is contained in:
commit
65449ffd71
1 file changed
+87
-15
@@ -9,6 +9,8 @@ export const EXTERNAL_USER_ID_STORAGE_KEY = "userId";
|
||||
export const EXTERNAL_USER_INFO_STORAGE_KEY = "userInfo";
|
||||
export const GENERAL_QA_ROUTE = "/page/workspace/chats/new";
|
||||
|
||||
const YUSER_INFO_CACHE_KEY = "deerflow.yuserInfoByYUserId";
|
||||
|
||||
type UserDetailResponse = {
|
||||
data?: {
|
||||
id?: string;
|
||||
@@ -34,6 +36,84 @@ function readStoredYUserId(info: Record<string, unknown>): string {
|
||||
return value == null ? "" : String(value).trim();
|
||||
}
|
||||
|
||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function isUsableExternalValue(value: unknown): boolean {
|
||||
if (value == null) return false;
|
||||
if (typeof value !== "string") return true;
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return false;
|
||||
const lowered = trimmed.toLowerCase();
|
||||
return lowered !== "null" && lowered !== "undefined";
|
||||
}
|
||||
|
||||
function readYUserInfoCache(): Record<string, Record<string, unknown>> {
|
||||
if (typeof window === "undefined") return {};
|
||||
try {
|
||||
const raw = window.localStorage.getItem(YUSER_INFO_CACHE_KEY);
|
||||
if (!raw) return {};
|
||||
const parsed = JSON.parse(raw);
|
||||
if (!isPlainObject(parsed)) return {};
|
||||
const cache: Record<string, Record<string, unknown>> = {};
|
||||
for (const [key, value] of Object.entries(parsed)) {
|
||||
if (isPlainObject(value)) cache[key] = value;
|
||||
}
|
||||
return cache;
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function readCachedYUserInfo(yUserId: string): Record<string, unknown> {
|
||||
return readYUserInfoCache()[yUserId] ?? {};
|
||||
}
|
||||
|
||||
function writeCachedYUserInfo(yUserId: string, info: Record<string, unknown>): void {
|
||||
if (typeof window === "undefined") return;
|
||||
try {
|
||||
const cache = readYUserInfoCache();
|
||||
cache[yUserId] = info;
|
||||
window.localStorage.setItem(YUSER_INFO_CACHE_KEY, JSON.stringify(cache));
|
||||
} catch {
|
||||
/* noop */
|
||||
}
|
||||
}
|
||||
|
||||
function buildExternalUserInfo(
|
||||
yUserId: string,
|
||||
result: Record<string, unknown>,
|
||||
previous: Record<string, unknown>,
|
||||
cached: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
const next: Record<string, unknown> = { ...cached };
|
||||
for (const [key, value] of Object.entries(result)) {
|
||||
if (isUsableExternalValue(value)) {
|
||||
next[key] = value;
|
||||
}
|
||||
}
|
||||
next.yUserId = yUserId;
|
||||
|
||||
const incomingAccessToken = normalizeExternalAccessToken(result.accessToken);
|
||||
if (incomingAccessToken) {
|
||||
next.accessToken = incomingAccessToken;
|
||||
return next;
|
||||
}
|
||||
|
||||
const previousYUserId = readStoredYUserId(previous);
|
||||
const previousAccessToken =
|
||||
previousYUserId === yUserId ? normalizeExternalAccessToken(previous.accessToken) : "";
|
||||
const cachedAccessToken = normalizeExternalAccessToken(cached.accessToken);
|
||||
const fallbackAccessToken = previousAccessToken || cachedAccessToken;
|
||||
if (fallbackAccessToken) {
|
||||
next.accessToken = fallbackAccessToken;
|
||||
} else {
|
||||
delete next.accessToken;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* External login via yUserId + optional token (same flow as web-code Login.tsx):
|
||||
* persist tools_token, resolve user via consumer API, store userId/userInfo.
|
||||
@@ -58,22 +138,10 @@ export async function loginByYUserId(
|
||||
// access_token,故登录流程随后会用 persistAccessToken 覆盖 userInfo.accessToken。
|
||||
const result = res.data ?? {};
|
||||
const previous = readExternalUserInfo();
|
||||
const next: Record<string, unknown> = { ...result, yUserId };
|
||||
const incomingAccessToken = normalizeExternalAccessToken(result.accessToken);
|
||||
if (incomingAccessToken) {
|
||||
next.accessToken = incomingAccessToken;
|
||||
} else {
|
||||
const previousAccessToken = normalizeExternalAccessToken(previous.accessToken);
|
||||
const previousYUserId = readStoredYUserId(previous);
|
||||
// Do not let an unstable upstream empty/null token wipe a usable token for
|
||||
// the same external user. Avoid carrying it across different yUserId values.
|
||||
if (previousAccessToken && previousYUserId === yUserId) {
|
||||
next.accessToken = previousAccessToken;
|
||||
} else {
|
||||
delete next.accessToken;
|
||||
}
|
||||
}
|
||||
const cached = readCachedYUserInfo(yUserId);
|
||||
const next = buildExternalUserInfo(yUserId, result, previous, cached);
|
||||
authStorageSet(EXTERNAL_USER_INFO_STORAGE_KEY, JSON.stringify(next));
|
||||
writeCachedYUserInfo(yUserId, next);
|
||||
}
|
||||
|
||||
export function persistToolsToken(token: string): void {
|
||||
@@ -93,4 +161,8 @@ export function persistAccessToken(token: string): void {
|
||||
const info = readExternalUserInfo();
|
||||
info.accessToken = trimmed;
|
||||
authStorageSet(EXTERNAL_USER_INFO_STORAGE_KEY, JSON.stringify(info));
|
||||
const yUserId = readStoredYUserId(info);
|
||||
if (yUserId) {
|
||||
writeCachedYUserInfo(yUserId, info);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user