mirror of
https://github.com/HeyPuter/puter.git
synced 2026-11-14 09:50:49 +00:00
fix: an unreadable plan is not a free plan (PUT-1843)
The Home tab read /marketplace/subscriptions/current and folded every failure into the free state: a non-OK response left `subscription` null, and the catch said so explicitly. So a refusal rendered as a confident "Free" with an Upgrade badge. That is reachable: verification gates are default-on for authenticated routes, and a team seat that still owes its password change is refused there — it then reads Free while its team pays for a tier. A rate limit or a blip does the same to anyone. The plan card moves into its own method so a failed read can return without touching it, leaving the card as it was rather than naming a plan the account does not have. A 200 carrying no subscription still reads Free, which is the one case that actually means it.
This commit is contained in:
1 parent
51ce868d1e
commit
e50d210423
1 file changed
+26
-21
@@ -427,27 +427,28 @@ const TabHome = {
|
||||
}
|
||||
},
|
||||
|
||||
async _loadUsageDataUncached($el_window) {
|
||||
// Load plan data — fetch live from /marketplace/subscriptions/current
|
||||
// rather than reading `window.user.subscription` (which is set once
|
||||
// from whoami at page-load and goes stale after subscribe / portal
|
||||
// cancel until a hard refresh).
|
||||
/**
|
||||
* The plan card, read live rather than from the whoami copy, which goes
|
||||
* stale. Not knowing the plan is not the same as being on the free one,
|
||||
* so a read that fails returns without touching the card.
|
||||
*/
|
||||
async _renderPlanCard($el_window) {
|
||||
let subscription = null;
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`${window.api_origin}/marketplace/subscriptions/current`,
|
||||
{ headers: { Authorization: `Bearer ${puter.authToken}` } },
|
||||
);
|
||||
// A refusal is not a free plan: a seat owing a password change 403s.
|
||||
if (!resp.ok) return;
|
||||
const data = await resp.json();
|
||||
subscription = data?.subscription ?? null;
|
||||
} catch (e) {
|
||||
console.error('Failed to load plan data:', e);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let subscription = null;
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`${window.api_origin}/marketplace/subscriptions/current`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${puter.authToken}` },
|
||||
},
|
||||
);
|
||||
if (resp.ok) {
|
||||
const data = await resp.json();
|
||||
subscription = data?.subscription ?? null;
|
||||
}
|
||||
} catch {
|
||||
// fall through to free state
|
||||
}
|
||||
|
||||
const pastDue =
|
||||
!!subscription && subscription.status === 'past_due';
|
||||
@@ -535,8 +536,12 @@ const TabHome = {
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Failed to load plan data:', e);
|
||||
console.error('Failed to render plan card:', e);
|
||||
}
|
||||
},
|
||||
|
||||
async _loadUsageDataUncached($el_window) {
|
||||
await this._renderPlanCard($el_window);
|
||||
|
||||
// Load storage data
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user