Fix subscription write error

This commit is contained in:
Corey Blais
2026-04-16 21:20:17 -04:00
parent 09a2b9f4a3
commit 2ae09149a5
+28 -5
View File
@@ -947,6 +947,11 @@ const requireWorkspaceRole = (allowedRoles: WorkspaceRole[]) => (req: Request, r
next(); next();
}; };
const isBillingOnlyWorkspaceUpdate = (
workspace: WorkspaceRow,
payload: z.infer<typeof workspaceSchema>,
) => workspace.workspace_type === 'standard' && payload.workspaceType === 'standard' && payload.name === workspace.name;
app.get('/api/health', (_req: Request, res: Response) => { app.get('/api/health', (_req: Request, res: Response) => {
res.json({ ok: true }); res.json({ ok: true });
}); });
@@ -1514,7 +1519,7 @@ app.get('/api/workspace', requireAuth, async (req: Request, res: Response) => {
res.json({ workspace: normalizeWorkspace(req.auth!.workspace) }); res.json({ workspace: normalizeWorkspace(req.auth!.workspace) });
}); });
app.put('/api/workspace', requireAuth, requireWriteAccess, requireWorkspaceRole(['owner', 'assistant']), async (req: Request, res: Response, next: NextFunction) => { app.put('/api/workspace', requireAuth, requireSessionAuth, requireWorkspaceRole(['owner', 'assistant']), async (req: Request, res: Response, next: NextFunction) => {
const parsed = workspaceSchema.safeParse(req.body); const parsed = workspaceSchema.safeParse(req.body);
if (!parsed.success) { if (!parsed.success) {
@@ -1523,17 +1528,35 @@ app.put('/api/workspace', requireAuth, requireWriteAccess, requireWorkspaceRole(
} }
try { try {
const billingPlan = resolveBillingPlan(parsed.data.workspaceType, parsed.data.billingPlan ?? req.auth!.workspace.billing_plan); const currentWorkspace = req.auth!.workspace;
const billingPlan = resolveBillingPlan(parsed.data.workspaceType, parsed.data.billingPlan ?? currentWorkspace.billing_plan);
const billingInterval = parsed.data.workspaceType === 'rescue' ? 'monthly' : (parsed.data.billingInterval ?? currentWorkspace.billing_interval);
const canUpdateWorkspace =
isAdminUser(req.auth!.user) ||
subscriptionAllowsWrite(currentWorkspace) ||
isBillingOnlyWorkspaceUpdate(currentWorkspace, parsed.data);
if (!canUpdateWorkspace) {
res.status(402).json({
error:
currentWorkspace.workspace_type === 'rescue'
? 'This rescue flock is read-only until FlockPal verifies it.'
: 'This flock is read-only until the subscription is restored.',
code: 'workspace_read_only',
});
return;
}
const workspace = await updateWorkspace({ const workspace = await updateWorkspace({
workspaceId: req.auth!.workspace.id, workspaceId: currentWorkspace.id,
name: parsed.data.name, name: parsed.data.name,
workspaceType: parsed.data.workspaceType, workspaceType: parsed.data.workspaceType,
billingEmail: emptyToNull(parsed.data.billingEmail), billingEmail: emptyToNull(parsed.data.billingEmail),
billingPlan, billingPlan,
billingInterval: parsed.data.workspaceType === 'rescue' ? 'monthly' : (parsed.data.billingInterval ?? req.auth!.workspace.billing_interval), billingInterval,
}); });
if (workspace?.workspace_type === 'rescue' && req.auth!.workspace.workspace_type !== 'rescue') { if (workspace?.workspace_type === 'rescue' && currentWorkspace.workspace_type !== 'rescue') {
await sendRescueStatusNotification({ await sendRescueStatusNotification({
workspace, workspace,
ownerEmail: req.auth!.user.email, ownerEmail: req.auth!.user.email,