[🛠️ Fix] Invalid log dir path (#24) & Remove PLS trust token

1. [-] 删除了 PLS 的 Trust token 认证机制
2. [+] 现在可以在 `偏好设置` - `调试选项` 中直接打开日志文件夹了
3. [/] 日志目录不再使用 `%USERPROFILE%\Documents\HugoAura\logs` 为基准, 而是从注册表获取值
4. [/] 配置文件目录同理, 旧版配置文件将会自动迁移到新位置
This commit is contained in:
Minoricew
2025-06-16 21:24:10 +08:00
parent dae0f033a5
commit a638a29cc6
13 changed files with 274 additions and 88 deletions

View File

@@ -77,6 +77,7 @@ const buildIpcMain = (electron) => {
}; };
const { applyBaseIpcHandler } = require("./ipcModules/baseIpcHandler"); const { applyBaseIpcHandler } = require("./ipcModules/baseIpcHandler");
const { applyDebugIpcHandler } = require("./ipcModules/debugIpcHandler");
const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler"); const { applyConfigIpcHandler } = require("./ipcModules/configIpcHandler");
const { applyFsIpcHandler } = require("./ipcModules/fsIpcHandler"); const { applyFsIpcHandler } = require("./ipcModules/fsIpcHandler");
const { applyPlsIpcHandler } = require("./ipcModules/plsIpcHandler"); const { applyPlsIpcHandler } = require("./ipcModules/plsIpcHandler");
@@ -87,6 +88,7 @@ const buildIpcMain = (electron) => {
}); });
applyBaseIpcHandler(ipcMain); applyBaseIpcHandler(ipcMain);
applyDebugIpcHandler(ipcMain);
applyConfigIpcHandler(ipcMain); applyConfigIpcHandler(ipcMain);
applyFsIpcHandler(ipcMain); applyFsIpcHandler(ipcMain);
applyPlsIpcHandler(ipcMain); applyPlsIpcHandler(ipcMain);

View File

@@ -1,59 +1,59 @@
// @ts-check // @ts-check
const { BrowserWindow } = require("electron"); const { BrowserWindow } = require("electron");
const composables = { const composables = {
getBrowserWindowInstance: (windowKey) => { getBrowserWindowInstance: (windowKey) => {
if (!global.__HUGO_AURA__.hookedWindows) return null; if (!global.__HUGO_AURA__.hookedWindows) return null;
const hookedWindowIns = global.__HUGO_AURA__.hookedWindows.get(windowKey); const hookedWindowIns = global.__HUGO_AURA__.hookedWindows.get(windowKey);
if (!hookedWindowIns) return undefined; if (!hookedWindowIns) return undefined;
const browserWindowIns = BrowserWindow.fromWebContents( const browserWindowIns = BrowserWindow.fromWebContents(
hookedWindowIns.webContents hookedWindowIns.webContents
); );
return browserWindowIns; return browserWindowIns;
}, },
}; };
/** /**
* *
* @param {import("electron").IpcMain} ipcMain * @param {import("electron").IpcMain} ipcMain
*/ */
const applyBaseIpcHandler = (ipcMain) => { const applyBaseIpcHandler = (ipcMain) => {
const methodBase = "$aura.base"; const methodBase = "$aura.base";
ipcMain.on( ipcMain.on(
`${methodBase}.minimizeWindow`, `${methodBase}.minimizeWindow`,
/** /**
* *
* @param {import("electron").IpcMainEvent} _event * @param {import("electron").IpcMainEvent} _event
* @param {{ targetWindowKey: string }} arg * @param {{ targetWindowKey: string }} arg
*/ */
(_event, arg) => { (_event, arg) => {
const browserWindowIns = composables.getBrowserWindowInstance( const browserWindowIns = composables.getBrowserWindowInstance(
arg.targetWindowKey arg.targetWindowKey
); );
if (!browserWindowIns) return; if (!browserWindowIns) return;
browserWindowIns.minimize(); browserWindowIns.minimize();
} }
); );
ipcMain.on( ipcMain.on(
`${methodBase}.closeWindow`, `${methodBase}.closeWindow`,
/** /**
* *
* @param {import("electron").IpcMainEvent} _event * @param {import("electron").IpcMainEvent} _event
* @param {{ targetWindowKey: string }} arg * @param {{ targetWindowKey: string }} arg
*/ */
(_event, arg) => { (_event, arg) => {
const browserWindowIns = composables.getBrowserWindowInstance( const browserWindowIns = composables.getBrowserWindowInstance(
arg.targetWindowKey arg.targetWindowKey
); );
if (!browserWindowIns) return; if (!browserWindowIns) return;
browserWindowIns.close(); browserWindowIns.close();
} }
); );
}; };
module.exports = { applyBaseIpcHandler }; module.exports = { applyBaseIpcHandler };

View File

@@ -0,0 +1,20 @@
// @ts-check
const __SCOPE = "main";
/**
*
* @param {import("electron").IpcMain} ipcMain
*/
const applyDebugIpcHandler = (ipcMain) => {
const methodBase = "$aura.debug";
ipcMain.handle(`${methodBase}.getLogDirAsync`, (_evt, _arg) => {
return {
success: true,
data: global.__HUGO_AURA__.logDir,
};
});
};
module.exports = { applyDebugIpcHandler };

View File

@@ -2,13 +2,43 @@ const path = require("path");
const fs = require("fs"); const fs = require("fs");
const os = require("os"); const os = require("os");
const util = require("util"); const util = require("util");
const RegistryManager = require("../shared/registryManager");
const getUserDocumentsDirPath = () => {
const registryManager = new RegistryManager();
const pathInfo = registryManager.readRegKeySync(
'"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"',
"Personal",
false,
true,
/REG_EXPAND_SZ\s+(.+)/
);
if (pathInfo.success) {
const resolvedPath = pathInfo.data.replace(
/%([^%]+)%/g,
(match, varName) => {
return process.env[varName] || match;
}
);
return resolvedPath;
} else {
console.error(
"[HugoAura / Init / Logger] Failed to get the path of documents dir, using default val."
);
return path.join(os.homedir(), "Documents");
}
};
/** /**
* *
* @param {import("../aura/types/main/core").WindowName} windowName * @param {import("../aura/types/main/core").WindowName} windowName
*/ */
const initLogger = (windowName) => { const initLogger = (windowName) => {
const logDir = path.join(os.homedir(), "Documents", "HugoAura", "logs"); const logDir = path.join(getUserDocumentsDirPath(), "HugoAura", "logs");
global.__HUGO_AURA__.logDir = logDir;
if (!fs.existsSync(logDir)) { if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true }); fs.mkdirSync(logDir, { recursive: true });
} }
@@ -64,25 +94,22 @@ const initLogger = (windowName) => {
console.error("[CRITICAL] UNCAUGHT EXCEPTION:", err); console.error("[CRITICAL] UNCAUGHT EXCEPTION:", err);
}); });
console.log( console.log("[HugoAura / Logger] Logger initialized. Log file:", logFile);
"[HugoAura / Logger] Logger initialized. Log file:",
logFile
);
}; };
const cleanupOldLogs = (logDir) => { const cleanupOldLogs = (logDir) => {
try { try {
const files = fs.readdirSync(logDir); const files = fs.readdirSync(logDir);
const now = new Date(); const now = new Date();
const sevenDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); const daysAgo = new Date(now.getTime() - 15 * 24 * 60 * 60 * 1000);
files.forEach((file) => { files.forEach((file) => {
if (file.endsWith(".log")) { if (file.endsWith(".log")) {
const filePath = path.join(logDir, file); const filePath = path.join(logDir, file);
const stats = fs.statSync(filePath); const stats = fs.statSync(filePath);
// 如果文件创建时间超过 30 天, 则删除 // 如果文件创建时间超过两周, 则删除
if (stats.birthtime < sevenDaysAgo) { if (stats.birthtime < daysAgo) {
fs.unlinkSync(filePath); fs.unlinkSync(filePath);
console.log( console.log(
`[HugoAura / Logger / Cleanup] Cleaned log file: ${file}` `[HugoAura / Logger / Cleanup] Cleaned log file: ${file}`
@@ -91,7 +118,10 @@ const cleanupOldLogs = (logDir) => {
} }
}); });
} catch (error) { } catch (error) {
console.error("[HugoAura / Logger / Cleanup] Unexpected error occurred cleaning log file:", error); console.error(
"[HugoAura / Logger / Cleanup] Unexpected error occurred cleaning log file:",
error
);
} }
}; };

View File

@@ -69,7 +69,7 @@ const deepMerge = (target, source) => {
class ConfigManager { class ConfigManager {
constructor() { constructor() {
this.configDir = path.join(os.homedir(), "Documents", "HugoAura"); this.configDir = path.join(global.__HUGO_AURA__.logDir, "..");
this.configPath = path.join(this.configDir, "config.json"); this.configPath = path.join(this.configDir, "config.json");
this.encConfigPath = path.join(this.configDir, ".cache_2eafc8d0.dat"); // (雾 this.encConfigPath = path.join(this.configDir, ".cache_2eafc8d0.dat"); // (雾
/* ↑ 不使用 .tmp 扩展名, 不然容易真被清理了 */ /* ↑ 不使用 .tmp 扩展名, 不然容易真被清理了 */
@@ -95,6 +95,33 @@ class ConfigManager {
} }
} }
migrateOldConfigFile() {
const oldConfigPath = path.join(
os.homedir(),
"Documents",
"HugoAura",
"config.json"
);
const oldEncConfigPath = path.join(
os.homedir(),
"Documents",
"HugoAura",
".cache_2eafc8d0.dat"
);
if (fs.existsSync(oldConfigPath)) {
fs.copyFileSync(oldConfigPath, this.configPath);
fs.unlinkSync(oldConfigPath);
} else if (fs.existsSync(oldEncConfigPath)) {
fs.copyFileSync(oldEncConfigPath, this.encConfigPath);
fs.unlinkSync(oldEncConfigPath);
this.useEncConfig = true;
}
console.log(
`[HugoAura / Config] Moved old config file to ${this.configDir}`
);
}
getHugoAuraConfigPath() { getHugoAuraConfigPath() {
return path.dirname( return path.dirname(
this.useEncConfig ? this.encConfigPath : this.configPath this.useEncConfig ? this.encConfigPath : this.configPath

View File

@@ -6,7 +6,12 @@ const { exec, execSync } = require("child_process");
const LOG_PREFIX = "[HugoAura / Init / Reg"; const LOG_PREFIX = "[HugoAura / Init / Reg";
const LOG_PREFIX_FUNC = "[HugoAura / Reg"; const LOG_PREFIX_FUNC = "[HugoAura / Reg";
const AURA_REGISTRY_PATH = ["HKEY_USERS", ".DEFAULT", "SOFTWARE", "HugoAura"].join("\\"); const AURA_REGISTRY_PATH = [
"HKEY_USERS",
".DEFAULT",
"SOFTWARE",
"HugoAura",
].join("\\");
class RegistryManager { class RegistryManager {
/** /**
@@ -341,19 +346,27 @@ class RegistryManager {
} }
/** /**
* @param {string} relativePath * @param {string} keyPath
* @param {string} keyName * @param {string} keyName
* @param {boolean | undefined} silent * @param {boolean | undefined} silent
* @param {boolean} absolute
* @param {any} regex
* @returns {Promise<{ success: boolean, data: string | null, error: Error | null }>} * @returns {Promise<{ success: boolean, data: string | null, error: Error | null }>}
*/ */
async readRegKey(relativePath, keyName, silent = false) { async readRegKey(
keyPath,
keyName,
silent = false,
absolute = false,
regex = null
) {
try { try {
const { stdout } = await new Promise((resolve, reject) => { const { stdout } = await new Promise((resolve, reject) => {
exec( exec(
[ [
"reg", "reg",
"query", "query",
[AURA_REGISTRY_PATH, relativePath].join("\\"), absolute ? keyPath : [AURA_REGISTRY_PATH, keyPath].join("\\"),
"/v", "/v",
`\"${keyName}\"`, `\"${keyName}\"`,
].join(" "), ].join(" "),
@@ -367,12 +380,12 @@ class RegistryManager {
if (!silent) { if (!silent) {
console.debug( console.debug(
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${relativePath}/${keyName}, stdout:`, `${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${keyPath}/${keyName}, stdout:`,
stdout stdout
); );
} }
const match = stdout.match(/REG_SZ\s+(.+)/); const match = regex ? stdout.match(regex) : stdout.match(/REG_SZ\s+(.+)/);
if (!match) { if (!match) {
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`); console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);
@@ -390,10 +403,7 @@ class RegistryManager {
error: null, error: null,
}; };
} catch (e) { } catch (e) {
console.error( console.error(`${LOG_PREFIX} / ERROR] Failed to read reg key, error:`, e);
`${LOG_PREFIX} / ERROR] Failed to read reg key, error:`,
e
);
return { return {
success: false, success: false,
data: null, data: null,
@@ -403,18 +413,26 @@ class RegistryManager {
} }
/** /**
* @param {string} relativePath * @param {string} keyPath
* @param {string} keyName * @param {string} keyName
* @param {boolean | undefined} silent * @param {boolean | undefined} silent
* @param {boolean} absolute
* @param {any} regex
* @returns {{ success: boolean, data: string | null, error: Error | null }} * @returns {{ success: boolean, data: string | null, error: Error | null }}
*/ */
readRegKeySync(relativePath, keyName, silent = false) { readRegKeySync(
keyPath,
keyName,
silent = false,
absolute = false,
regex = null
) {
try { try {
const readResult = execSync( const readResult = execSync(
[ [
"reg", "reg",
"query", "query",
[AURA_REGISTRY_PATH, relativePath].join("\\"), absolute ? keyPath : [AURA_REGISTRY_PATH, keyPath].join("\\"),
"/v", "/v",
`\"${keyName}\"`, `\"${keyName}\"`,
].join(" "), ].join(" "),
@@ -424,11 +442,13 @@ class RegistryManager {
if (readResult) { if (readResult) {
if (!silent) { if (!silent) {
console.debug( console.debug(
`${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${relativePath}/${keyName}, stdout:`, `${LOG_PREFIX_FUNC} / SUCCESS] Successfully read reg key ${keyPath}/${keyName}, stdout:`,
readResult readResult
); );
} }
const match = readResult.match(/REG_SZ\s+(.+)/); const match = regex
? readResult.match(regex)
: readResult.match(/REG_SZ\s+(.+)/);
if (!match) { if (!match) {
console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`); console.warn(`${LOG_PREFIX} / WARN] Data not found in stdout`);

View File

@@ -14,6 +14,7 @@ interface GlobalHugoAuraInfo {
fsTasks?: MainProcessOnlyVal<FSTasks>; fsTasks?: MainProcessOnlyVal<FSTasks>;
hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>; hookedWindows?: MainProcessOnlyVal<HookedWindowsMap>;
ipcInit?: MainProcessOnlyVal<boolean>; ipcInit?: MainProcessOnlyVal<boolean>;
logDir: MainProcessOnlyVal<string>;
plsRules?: Record<any, any> | null; plsRules?: Record<any, any> | null;
plsSettings?: Record<any, any> | null; plsSettings?: Record<any, any> | null;
plsStats?: PLSStatus | null; plsStats?: PLSStatus | null;

View File

@@ -170,6 +170,23 @@ const renderInputArea = (entry, operationArea, descriptionArea) => {
operationArea.classList.add("ase-operation-area-expanded"); operationArea.classList.add("ase-operation-area-expanded");
return inputEl; return inputEl;
} }
case "button": {
const btnEl = document.createElement("button");
btnEl.type = "button";
btnEl.classList.add("btn");
switch (entry.style) {
case "outline":
default:
btnEl.classList.add("btn-outline-primary");
break;
}
btnEl.innerHTML = entry.buttonContent;
btnEl.onclick = entry.callbackFn;
(async () => {
descriptionArea.innerHTML = await entry.valueGetter();
})();
return btnEl;
}
default: default:
break; break;
} }

View File

@@ -45,8 +45,7 @@
}; };
const calcFullAuthToken = (/** @type {string} */ authToken) => { const calcFullAuthToken = (/** @type {string} */ authToken) => {
const trustToken = window._ACCEPT_DATA.getData("deviceId"); const conjToken = authToken + "AuraXAuth 0xFFFFFF NeverEnds";
const conjToken = authToken + "AuraXAuth" + trustToken + "NeverEnds";
const crypto = require("crypto"); const crypto = require("crypto");
return crypto.createHash("sha512").update(conjToken).digest("hex"); return crypto.createHash("sha512").update(conjToken).digest("hex");
}; };

View File

@@ -17,6 +17,20 @@
Aura 设置 Aura 设置
</button> </button>
</li> </li>
<li class="nav-item" role="presentation">
<button
class="nav-link"
id="debug-subpage-tab"
data-bs-toggle="pill"
data-bs-target="#debug-subpage"
type="button"
role="tab"
aria-controls="debug-subpage"
aria-selected="false"
>
调试选项
</button>
</li>
<li class="nav-item" role="presentation"> <li class="nav-item" role="presentation">
<button <button
class="nav-link" class="nav-link"
@@ -26,7 +40,7 @@
type="button" type="button"
role="tab" role="tab"
aria-controls="about-subpage" aria-controls="about-subpage"
aria-selected="true" aria-selected="false"
> >
关于项目 关于项目
</button> </button>
@@ -39,6 +53,12 @@
role="tabpanel" role="tabpanel"
aria-labelledby="aura-subpage-tab" aria-labelledby="aura-subpage-tab"
></div> ></div>
<div
class="tab-pane fade"
id="debug-subpage"
role="tabpanel"
aria-labelledby="debug-subpage-tab"
></div>
<div <div
class="tab-pane fade" class="tab-pane fade"
id="about-subpage" id="about-subpage"

View File

@@ -5,13 +5,21 @@
settingsRenderer, settingsRenderer,
} = require("../../aura/ui/composables/settingsRenderer"); } = require("../../aura/ui/composables/settingsRenderer");
const { auraSettings } = require(`${pathBase}/aura`); const { auraSettings } = require(`${pathBase}/aura`);
const { debugSettings } = require(`${pathBase}/debug`);
const initAuraSubPage = () => { const initAuraSubPage = () => {
const auraSettingsSubPageEl = document.getElementById("aura-subpage"); const auraSettingsSubPageEl = document.getElementById("aura-subpage");
settingsRenderer(auraSettingsSubPageEl, auraSettings); settingsRenderer(auraSettingsSubPageEl, auraSettings);
}; };
const initDebugSubPage = () => {
const debugSubPageEl = document.getElementById("debug-subpage");
settingsRenderer(debugSubPageEl, debugSettings);
};
const onMounted = () => { const onMounted = () => {
initAuraSubPage(); initAuraSubPage();
initDebugSubPage();
const rootEl = document.getElementById("acs-preferences-root-el"); const rootEl = document.getElementById("acs-preferences-root-el");
setTimeout(() => { setTimeout(() => {

View File

@@ -0,0 +1,40 @@
const IPC_METHOD_BASE = "$aura.debug";
const debugSettings = [
{
id: 0,
categoryName: "日志与输出",
child: [
{
index: 0,
id: "openHugoAuraLogDir",
type: "button",
style: "outline",
name: "HugoAura 日志目录",
description: "",
restart: false,
reload: false,
associateVal: null,
auraIf: () => true,
buttonContent: "打开",
valueGetter: async () => {
const ipcRendererRet = await ipcRenderer.invoke(
`${IPC_METHOD_BASE}.getLogDirAsync`
);
if (ipcRendererRet.success && ipcRendererRet.data !== "") {
global.__HUGO_AURA__.logDir = ipcRendererRet.data;
return "目录位置: " + ipcRendererRet.data;
} else {
return "未能获取日志目录位置";
}
},
callbackFn: async (event) => {
const childProc = require("child_process");
childProc.spawn(`explorer.exe`, [`${global.__HUGO_AURA__.logDir}`]);
},
},
],
},
];
module.exports = { debugSettings };

View File

@@ -6,6 +6,7 @@ if (!global.__HUGO_AURA__) {
configInit: false, configInit: false,
central: () => {}, central: () => {},
ipcInit: false, ipcInit: false,
logDir: "",
plsStats: null, plsStats: null,
plsSettings: null, plsSettings: null,
plsRules: null, plsRules: null,
@@ -24,7 +25,7 @@ if (!global.__HUGO_AURA_API__) {
"https://api-aura.asaka.site", "https://api-aura.asaka.site",
"https://api.hugoaura.dpdns.org", "https://api.hugoaura.dpdns.org",
"https://api-aura-projekts.minorice.moe", "https://api-aura-projekts.minorice.moe",
"https://api.aura.vim.moe" "https://api.aura.vim.moe",
], ],
plsUpdate: "/api/getPLSLatestVersion", plsUpdate: "/api/getPLSLatestVersion",
auraUpdate: "/api/getAuraLatestVersion", auraUpdate: "/api/getAuraLatestVersion",
@@ -79,6 +80,7 @@ const launcher = ({ central, windowName, config }) => {
// >>> Init Config <<< // // >>> Init Config <<< //
const configManager = new ConfigManager(); const configManager = new ConfigManager();
configManager.side = "main"; configManager.side = "main";
configManager.migrateOldConfigFile();
configManager.ensureConfigExists(); configManager.ensureConfigExists();
const loadedConfig = configManager.loadConfig(); const loadedConfig = configManager.loadConfig();
if (!global.__HUGO_AURA__.configInit) global.__HUGO_AURA__.configInit = true; if (!global.__HUGO_AURA__.configInit) global.__HUGO_AURA__.configInit = true;