fix(account): bind pending downloads to user

This commit is contained in:
2026-05-19 01:02:53 +08:00
parent 4b81869b6e
commit b839e0770c
2 changed files with 85 additions and 4 deletions
+28 -4
View File
@@ -409,7 +409,12 @@ const favoriteLoading = ref(false);
const favoriteError = ref(""); const favoriteError = ref("");
const favoriteRequestGeneration = ref(0); const favoriteRequestGeneration = ref(0);
const systemInfo = ref<SystemInfo>({ distro: "unknown" }); const systemInfo = ref<SystemInfo>({ distro: "unknown" });
type PendingDownloadRecord = Omit<DownloadedAppRecord, "id" | "downloadedAt">; type PendingDownloadRecord = Omit<
DownloadedAppRecord,
"id" | "downloadedAt"
> & {
userId: number;
};
const pendingDownloadRecords = new Map<number, PendingDownloadRecord>(); const pendingDownloadRecords = new Map<number, PendingDownloadRecord>();
/** 启动参数 --no-apm => 仅 Spark--no-spark => 仅 APM;由主进程 IPC 提供 */ /** 启动参数 --no-apm => 仅 Spark--no-spark => 仅 APM;由主进程 IPC 提供 */
@@ -1245,9 +1250,11 @@ const onDetailRemove = (app: App) => {
const onDetailInstall = async (app: App) => { const onDetailInstall = async (app: App) => {
const download = await handleInstall(app); const download = await handleInstall(app);
if (!download || !isLoggedIn.value) return; const initiatingUserId = currentUser.value?.id;
if (!download || !isLoggedIn.value || initiatingUserId === undefined) return;
pendingDownloadRecords.set(download.id, { pendingDownloadRecords.set(download.id, {
userId: initiatingUserId,
appKey: buildFavoriteAppKey(app), appKey: buildFavoriteAppKey(app),
pkgname: app.pkgname, pkgname: app.pkgname,
name: app.name, name: app.name,
@@ -1265,10 +1272,26 @@ const handleInstallCompleteForDownloadRecord = async (
const pendingRecord = pendingDownloadRecords.get(result.id); const pendingRecord = pendingDownloadRecords.get(result.id);
if (!pendingRecord) return; if (!pendingRecord) return;
if (!result.success || !isLoggedIn.value) return; if (
!result.success ||
!isLoggedIn.value ||
currentUser.value?.id !== pendingRecord.userId
) {
return;
}
const downloadRecord: Omit<DownloadedAppRecord, "id" | "downloadedAt"> = {
appKey: pendingRecord.appKey,
pkgname: pendingRecord.pkgname,
name: pendingRecord.name,
category: pendingRecord.category,
selectedOrigin: pendingRecord.selectedOrigin,
version: pendingRecord.version,
packageArch: pendingRecord.packageArch,
};
try { try {
await recordDownloadedApp(pendingRecord); await recordDownloadedApp(downloadRecord);
} catch (error: unknown) { } catch (error: unknown) {
logger.warn({ err: error }, "记录下载应用失败"); logger.warn({ err: error }, "记录下载应用失败");
} finally { } finally {
@@ -1372,6 +1395,7 @@ const isCurrentFavoriteRequest = (generation: number): boolean =>
const handleLogout = () => { const handleLogout = () => {
logout(); logout();
pendingDownloadRecords.clear();
clearFavoriteState(); clearFavoriteState();
showLoginModal.value = false; showLoginModal.value = false;
showLoginPrompt.value = false; showLoginPrompt.value = false;
@@ -269,4 +269,61 @@ describe("App download records", () => {
); );
}); });
}); });
it("does not record a queued install under a later logged-in user", async () => {
render(App);
await fireEvent.click(
await screen.findByRole("button", { name: "全部应用 1" }),
);
await fireEvent.click(await screen.findByText("WPS"));
await fireEvent.click(await screen.findByRole("button", { name: "安装" }));
await waitFor(() => {
expect(send).toHaveBeenCalledWith(
"queue-install",
expect.stringContaining('"pkgname":"wps"'),
);
});
const queuedPayload = vi
.mocked(send)
.mock.calls.find(
([channel]) => channel === "queue-install",
)?.[1] as string;
const queuedDownload = JSON.parse(queuedPayload) as { id: number };
await fireEvent.click(screen.getByRole("button", { name: "Momen" }));
await fireEvent.click(await screen.findByText("退出登录"));
setAuthSession({
accessToken: "backend-token-b",
tokenType: "bearer",
user: {
id: 2,
flarumUserId: "84",
username: "second",
displayName: "Second User",
avatarUrl: "https://bbs.spark-app.store/avatar-b.png",
forumLevel: "用户",
forumGroups: ["用户"],
},
});
const completion: DownloadResult = {
id: queuedDownload.id,
time: Date.now(),
message: "installed",
success: true,
exitCode: 0,
status: "completed",
origin: "apm",
};
ipcHandlers.get("install-complete")?.({}, completion);
await waitFor(() => {
expect(recordDownloadedApp).not.toHaveBeenCalled();
});
});
}); });