diff --git a/.env.debug b/.env.debug index 637f41e3..30e7614a 100644 --- a/.env.debug +++ b/.env.debug @@ -1,3 +1,4 @@ VITE_APM_STORE_LOCAL_MODE=true VITE_APM_STORE_BASE_URL=/local_amd64-store VITE_APM_STORE_STATS_BASE_URL=/local_stats +VITE_SPARK_BACKEND_BASE_URL=http://127.0.0.1:8000 diff --git a/.gitignore b/.gitignore index c07a2ded..f4a7205f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,13 @@ dist-electron release *.local +# Local secrets and databases +.env +.env.*.local +*.sqlite +*.sqlite3 +*.db + # Test coverage coverage .nyc_output diff --git a/electron/main/index.ts b/electron/main/index.ts index 53cf19d1..2b4b8035 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -40,6 +40,23 @@ function getAppVersion(): string { } } +function getSystemInfo(): { distro: string } { + try { + const raw = fs.readFileSync("/etc/os-release", "utf8"); + const fields = Object.fromEntries( + raw + .split("\n") + .map((line) => line.match(/^([A-Z_]+)=(.*)$/)) + .filter((match): match is RegExpMatchArray => match !== null) + .map((match) => [match[1], match[2].replace(/^"|"$/g, "")]), + ); + const distro = fields.PRETTY_NAME || fields.NAME || "unknown"; + return { distro }; + } catch { + return { distro: "unknown" }; + } +} + // 处理 --version 参数(在单实例检查之前) if (process.argv.includes("--version") || process.argv.includes("-v")) { console.log(getAppVersion()); @@ -55,6 +72,7 @@ import "./backend/install-manager.js"; import "./handle-url-scheme.js"; const logger = pino({ name: "index.ts" }); +const FLARUM_TOKEN_URL = "https://bbs.spark-app.store/api/token"; // The built directory structure // @@ -117,6 +135,76 @@ ipcMain.handle("get-store-filter", (): "spark" | "apm" | "both" => ); ipcMain.handle("get-app-version", (): string => getAppVersion()); +ipcMain.handle("get-system-info", (): { distro: string } => getSystemInfo()); + +ipcMain.handle("request-flarum-token", async (_event, payload: unknown) => { + if (!payload || typeof payload !== "object" || Array.isArray(payload)) { + throw new Error("登录信息格式不正确,请重新输入。"); + } + + const credentials = payload as Record; + if ( + typeof credentials.identification !== "string" || + typeof credentials.password !== "string" + ) { + throw new Error("登录信息格式不正确,请重新输入。"); + } + + logger.info({ endpoint: FLARUM_TOKEN_URL }, "Requesting Flarum login token"); + + let response: Response; + try { + response = await fetch(FLARUM_TOKEN_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "User-Agent": getUserAgent(), + }, + body: JSON.stringify({ + identification: credentials.identification, + password: credentials.password, + }), + }); + } catch (err) { + logger.error( + { err, endpoint: FLARUM_TOKEN_URL }, + "Flarum token request failed before response", + ); + throw new Error("无法连接星火论坛,请检查网络后重试。"); + } + + if (!response.ok) { + logger.warn( + { endpoint: FLARUM_TOKEN_URL, status: response.status }, + "Flarum rejected login token request", + ); + throw new Error("论坛登录失败,请检查账号和密码。"); + } + + const data = (await response.json()) as Record; + const userId = data.userId ?? data.user_id; + if ( + typeof data.token !== "string" || + userId === undefined || + userId === null + ) { + logger.warn( + { + endpoint: FLARUM_TOKEN_URL, + hasToken: typeof data.token === "string" && data.token.length > 0, + hasUserId: userId !== undefined && userId !== null, + }, + "Flarum token response missing required fields", + ); + throw new Error("论坛登录响应异常,请稍后重试。"); + } + + return { + token: data.token, + userId: String(userId), + }; +}); const getMainWindowCloseGuardState = (): MainWindowCloseGuardState => ({ installTaskCount: tasks.size, diff --git a/src/App.vue b/src/App.vue index 1440c1cf..17b544e7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -24,11 +24,18 @@ :store-filter="storeFilter" :sidebar-entries="sidebarEntries" :entry-counts="entryCounts" + :current-user="currentUser" @toggle-theme="toggleTheme" @select-tab="selectTab" @close="isSidebarOpen = false" @list="handleList" @update="handleUpdate" + @request-login="showLoginModal = true" + @open-user-management="openUserManagement" + @open-favorites="openFavoriteManagement" + @open-forum="openExternalUrl(FLARUM_BASE_URL)" + @edit-profile="openExternalUrl(FLARUM_SETTINGS_URL)" + @logout="handleLogout" /> @@ -55,7 +62,54 @@ @select-category="selectSubCategory" />
-