fix: use admin client in onboarding guard to prevent accidental workspace creation
Session client (getUserTeams) can return null when the session token is expired or stale. The old guard 'if (teams && teams.total > 0) redirect' was bypassed when teams was null, allowing users to create duplicate workspaces. New guard uses admin client (API key, never session-dependent): - lists user memberships via users.listMemberships(userId) - checks for a tenant_settings row in this app - redirects to /dashboard if found; shows form only for genuinely new users
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { redirect } from "next/navigation";
|
||||
import { Query } from "node-appwrite";
|
||||
|
||||
import { getCurrentUser } from "@/lib/appwrite/server";
|
||||
import { getUserTeams, getCrossAppTeams } from "@/lib/appwrite/tenant";
|
||||
import { getCurrentUser, createAdminClient } from "@/lib/appwrite/server";
|
||||
import { getCrossAppTeams } from "@/lib/appwrite/tenant";
|
||||
import { DATABASE_ID, TABLES } from "@/lib/appwrite/schema";
|
||||
import { CreateWorkspaceForm } from "./components/create-workspace-form";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -14,8 +16,26 @@ export default async function OnboardingPage() {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) redirect("/sign-in");
|
||||
|
||||
const teams = await getUserTeams();
|
||||
if (teams && teams.total > 0) redirect("/dashboard");
|
||||
// Use admin client — never fails due to expired session tokens.
|
||||
// If user already has a team with CRM settings, send them to dashboard.
|
||||
try {
|
||||
const { users, tablesDB } = createAdminClient();
|
||||
const memberships = await users.listMemberships(user.$id);
|
||||
if (memberships.total > 0) {
|
||||
const teamIds = memberships.memberships.map((m) => m.teamId);
|
||||
const settings = await tablesDB.listRows({
|
||||
databaseId: DATABASE_ID,
|
||||
tableId: TABLES.tenantSettings,
|
||||
queries: [Query.equal("tenantId", teamIds), Query.limit(1)],
|
||||
});
|
||||
if (settings.rows.length > 0) redirect("/dashboard");
|
||||
}
|
||||
} catch {
|
||||
// Admin client uses an API key (not a session), so this is extremely rare.
|
||||
// If it does fail, show a 500 rather than silently letting the user create
|
||||
// a duplicate workspace.
|
||||
throw new Error("Onboarding guard check failed — server configuration issue.");
|
||||
}
|
||||
|
||||
const crossAppTeams = await getCrossAppTeams();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user