fix: harden getActiveContext and add error logging on presentations page

- getActiveContext now verifies team still exists (teams.get) before
  trusting the cookie/prefs tenantId, preventing stale E Ofis cookie
  from causing an onboarding redirect loop
- Resolved tenantId from getUserTeams() is now persisted to cookie so
  subsequent requests skip the resolution path
- Added catch+log on presentations data fetch to surface the actual
  error in server logs
This commit is contained in:
egecankomur
2026-05-12 15:33:38 +03:00
parent 84be9ec5e3
commit b71edd880b
2 changed files with 22 additions and 3 deletions
+4 -1
View File
@@ -25,7 +25,10 @@ export default async function PresentationsPage() {
Query.limit(200),
],
}),
]);
]).catch((e) => {
console.error("[PresentationsPage] data fetch failed:", e);
throw e;
});
const presentations = JSON.parse(JSON.stringify(presResult.rows)) as Presentation[];
+18 -2
View File
@@ -14,6 +14,18 @@ export type ActiveContext = {
settings: TenantSettings | null;
};
async function setActiveTenantCookie(tenantId: string) {
try {
(await cookies()).set(ACTIVE_TENANT_COOKIE, tenantId, {
path: "/",
httpOnly: true,
sameSite: "strict",
secure: process.env.NODE_ENV === "production",
maxAge: 60 * 60 * 24 * 365,
});
} catch { /* ignore in middleware context */ }
}
export async function getActiveContext(): Promise<ActiveContext | null> {
const user = await getCurrentUser();
if (!user) return null;
@@ -22,17 +34,19 @@ export async function getActiveContext(): Promise<ActiveContext | null> {
let tenantId = await getActiveTenantId();
// Validate cookie tenantId — user must actually be a member of that team.
// Validate cookie/prefs tenantId — team must exist and user must be a member.
if (tenantId) {
try {
await adminTeams.get(tenantId); // throws if team was deleted
const memberships = await adminTeams.listMemberships(tenantId);
const isMember = memberships.memberships.some((m) => m.userId === user.$id);
if (!isMember) {
// Stale or cross-account cookie — clear and re-resolve.
try { (await cookies()).delete(ACTIVE_TENANT_COOKIE); } catch { /* ignore */ }
tenantId = null;
}
} catch {
// Team deleted or inaccessible — clear stale pointer.
try { (await cookies()).delete(ACTIVE_TENANT_COOKIE); } catch { /* ignore */ }
tenantId = null;
}
}
@@ -40,6 +54,8 @@ export async function getActiveContext(): Promise<ActiveContext | null> {
if (!tenantId) {
const userTeams = await getUserTeams();
tenantId = userTeams?.teams[0]?.$id ?? null;
// Persist so the next request skips this resolution path.
if (tenantId) await setActiveTenantCookie(tenantId);
}
if (!tenantId) return null;