Duas lacunas impediam qualquer uso de homologação. Primeira: sem SSO do Elo Pro e sem o login local, não havia como entrar. Segunda, mais grave: nada no repositório gravava o cookie `elo_pro_workspace_id`, que era lido como origem do workspace ativo — mesmo com sessão válida a resposta era sempre "sem workspace". - `identity-provider.ts` define o contrato de identidade. Trocar o Supabase de homologação pelo SSO do Elo Pro passa a ser acrescentar uma implementação; nenhum outro arquivo conhece o mecanismo. - `/api/auth/staging/session` autentica com `signInWithPassword` no projeto Supabase de homologação. Há senha, emitida e validada pelo Supabase, e o Adaptador continua sem tabela de usuário, senha ou sessão própria. - O login local sem senha existe apenas em `ADAPTER_ENV=development`, e não por configuração: fora de development o provedor nem entra na lista. - `workspace.ts` resolve o workspace por associação real lida sob RLS. O cookie passa a ser preferência, não prova: aceitá-lo como autorização transformava um valor editável pelo cliente em credencial. - `/api/auth/workspace` grava a preferência só depois de confirmar a associação, e `/selecionar-workspace` existe para quem participa de mais de um workspace. - Rate limiting por usuário e bucket nas rotas do módulo, com Retry-After. Upload e processamento custam muito mais que leitura. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
import { redirect } from "next/navigation";
|
|
import { currentMemberships } from "@/server/auth/context";
|
|
import { safeReturnPath } from "@/server/auth/return-to";
|
|
import { WorkspacePicker } from "@/components/workspace-picker";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export default async function SelecionarWorkspacePage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<{ next?: string }>;
|
|
}) {
|
|
const params = await searchParams;
|
|
const nextPath = safeReturnPath(params.next);
|
|
const current = await currentMemberships();
|
|
if (!current) redirect(`/login?next=${encodeURIComponent(nextPath)}`);
|
|
if (current.memberships.length === 0) {
|
|
return (
|
|
<main className="mx-auto max-w-xl p-8">
|
|
<h1 className="text-2xl font-semibold">Nenhum workspace</h1>
|
|
<p className="mt-3 text-sm text-ink/80">
|
|
Sua identidade não está associada a nenhum workspace. Peça a um administrador do Elo Pro para incluir seu
|
|
acesso.
|
|
</p>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<main className="mx-auto max-w-xl p-8">
|
|
<p className="text-xs font-semibold tracking-wide text-bright">ELO PRO</p>
|
|
<h1 className="mt-2 text-2xl font-semibold">Workspace ativo</h1>
|
|
<WorkspacePicker memberships={current.memberships} next={nextPath} />
|
|
</main>
|
|
);
|
|
}
|