Files
auto-login/env-store.js
T
2026-09-14 14:40:59 +08:00

156 lines
4.9 KiB
JavaScript

/**
* 环境数据层:管理多环境配置。
*
* 数据存放在 chrome.storage.session(解锁后明文,内存中、不落盘)。
* 首次创建口令由 crypto-store.setupVault 完成(含预置环境)。
* 锁定时 session 被清空,本层返回空数据。
*
* 浏览器中通过全局 chrome.storage.session 存取;Node 测试中注入 mock。
*/
(function (root, factory) {
if (typeof module === "object" && module.exports) {
module.exports = factory({
getStorage: () => (typeof chrome !== "undefined" ? chrome.storage.session : null),
getLocalStorage: () => (typeof chrome !== "undefined" ? chrome.storage.local : null),
});
} else {
const api = factory({
getStorage: () => chrome.storage.session,
getLocalStorage: () => chrome.storage.local,
});
root.EnvStore = api;
}
})(typeof globalThis !== "undefined" ? globalThis : this, function ({ getStorage, getLocalStorage }) {
const ENV_KEY = "environments";
const ACTIVE_ENV_KEY = "activeEnvId";
function genId() {
return "env_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
}
function genCfgId() {
return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
}
function storage() {
const s = getStorage();
if (!s) throw new Error("chrome.storage.session 不可用");
return s;
}
/**
* 加载所有环境。未解锁时 session 为空,返回空数组。
*/
async function loadEnvironments() {
const data = await storage().get([ENV_KEY, ACTIVE_ENV_KEY]);
const environments = data[ENV_KEY] || [];
const activeEnvId = data[ACTIVE_ENV_KEY] || environments[0]?.id || null;
return { environments, activeEnvId };
}
async function saveEnvironments(environments, activeEnvId) {
const patch = { [ENV_KEY]: environments };
if (activeEnvId !== undefined) patch[ACTIVE_ENV_KEY] = activeEnvId;
await storage().set(patch);
}
async function getActiveEnv() {
const { environments, activeEnvId } = await loadEnvironments();
return environments.find((e) => e.id === activeEnvId) || environments[0] || null;
}
async function setActiveEnv(envId) {
await storage().set({ [ACTIVE_ENV_KEY]: envId });
}
const MAX_ENVIRONMENTS = 5;
async function createEnvironment(name) {
const { environments } = await loadEnvironments();
if (environments.length >= MAX_ENVIRONMENTS) {
throw new Error(`最多 ${MAX_ENVIRONMENTS} 个环境`);
}
const env = { id: genId(), name, configs: [] };
environments.push(env);
await saveEnvironments(environments, env.id);
return env;
}
async function renameEnvironment(envId, newName) {
const { environments } = await loadEnvironments();
const env = environments.find((e) => e.id === envId);
if (env) {
env.name = newName;
await saveEnvironments(environments);
}
return env;
}
async function deleteEnvironment(envId) {
const { environments, activeEnvId } = await loadEnvironments();
if (environments.length <= 1) {
throw new Error("至少保留一个环境");
}
const idx = environments.findIndex((e) => e.id === envId);
if (idx === -1) return;
environments.splice(idx, 1);
const newActive = activeEnvId === envId ? environments[0].id : activeEnvId;
await saveEnvironments(environments, newActive);
// 清理该环境的失败计数(失败计数非敏感,存于 local 持久化)
const local = getLocalStorage();
if (local) {
const attemptsData = await local.get("loginAttempts");
const attempts = attemptsData.loginAttempts || {};
Object.keys(attempts).forEach((k) => {
if (k.startsWith(envId + "::")) delete attempts[k];
});
await local.set({ loginAttempts: attempts });
}
}
/** 当前激活环境的配置列表 */
async function loadConfigs() {
const env = await getActiveEnv();
return env?.configs || [];
}
/** 覆盖保存当前激活环境的配置 */
async function saveConfigs(configs) {
const { environments, activeEnvId } = await loadEnvironments();
const env = environments.find((e) => e.id === activeEnvId);
if (!env) throw new Error("未找到当前环境");
env.configs = configs;
await saveEnvironments(environments);
}
/** 扁平化所有环境的配置,附带 envId / envName(用于全局匹配) */
async function loadAllConfigs() {
const { environments } = await loadEnvironments();
const all = [];
environments.forEach((env) => {
(env.configs || []).forEach((cfg) => {
all.push({ ...cfg, envId: env.id, envName: env.name });
});
});
return all;
}
return {
ENV_KEY,
ACTIVE_ENV_KEY,
MAX_ENVIRONMENTS,
loadEnvironments,
saveEnvironments,
getActiveEnv,
setActiveEnv,
createEnvironment,
renameEnvironment,
deleteEnvironment,
loadConfigs,
saveConfigs,
loadAllConfigs,
genId,
genCfgId,
};
});