forked from Goutam/lynkeduppro-crm
feat(auth): gate Google sign-in on an existing CRM profile
Google is sign-IN only: after OAuth, check crm.account.registrationStatus; if the account has no CRM profile, sign back out and show an error on the login screen instead of admitting a profile-less user. (Onboarding to collect the profile comes later.)
This commit is contained in:
@@ -24,8 +24,8 @@ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
export function LoginFlow() {
|
||||
const router = useRouter();
|
||||
const { login, loginWithOAuth, completeOAuthLogin } = useAuth();
|
||||
const { ready } = useAppShell();
|
||||
const { login, loginWithOAuth, completeOAuthLogin, logout } = useAuth();
|
||||
const { ready, sdk } = useAppShell();
|
||||
const [step, setStep] = useState<Step>("identify");
|
||||
const [email, setEmail] = useState("");
|
||||
const [account, setAccount] = useState<Account | null>(null);
|
||||
@@ -76,20 +76,29 @@ export function LoginFlow() {
|
||||
if (!ready) { setStep("connecting"); return; }
|
||||
setStep("connecting");
|
||||
completeOAuthLogin(code)
|
||||
.then((ace) => {
|
||||
if (ace) {
|
||||
// Clear the ?code=… from the URL, then enter the app.
|
||||
.then(async (ace) => {
|
||||
if (!ace) { replace("identify"); return; }
|
||||
// Google is sign-IN only: require an existing CRM profile. If the account
|
||||
// has none, sign back out and show an error rather than silently admitting it.
|
||||
let registered = false;
|
||||
try {
|
||||
const st = await sdk.query<{ registered: boolean }>("crm.account.registrationStatus");
|
||||
registered = !!st?.registered;
|
||||
} catch { registered = false; }
|
||||
window.history.replaceState({}, "", "/portal/login");
|
||||
router.replace("/dashboard");
|
||||
} else {
|
||||
if (!registered) {
|
||||
try { await logout(); } catch { /* ignore */ }
|
||||
setFlash("No account is registered for this Google email. Please register first.");
|
||||
replace("identify");
|
||||
return;
|
||||
}
|
||||
router.replace("/dashboard");
|
||||
})
|
||||
.catch(() => {
|
||||
setFlash("Google sign-in didn't complete. Please try again.");
|
||||
replace("identify");
|
||||
});
|
||||
}, [ready, completeOAuthLogin, router]);
|
||||
}, [ready, completeOAuthLogin, router, sdk, logout]);
|
||||
|
||||
/* ---- auth resolution ---- */
|
||||
function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") {
|
||||
@@ -144,7 +153,12 @@ export function LoginFlow() {
|
||||
/* =================================================================== */
|
||||
return (
|
||||
<div className="card anim-fade-up" key={step}>
|
||||
{step === "identify" && <Identify email={email} setEmail={setEmail} onSocial={onSocial} onEmail={identifyEmail} onPhone={startPhoneLogin} toRegister={() => router.push("/portal/register")} />}
|
||||
{step === "identify" && (
|
||||
<>
|
||||
{flash && <div style={{ marginBottom: 16 }}><FlashNote tone="error">{flash}</FlashNote></div>}
|
||||
<Identify email={email} setEmail={setEmail} onSocial={onSocial} onEmail={identifyEmail} onPhone={startPhoneLogin} toRegister={() => router.push("/portal/register")} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{step === "connecting" && (
|
||||
<div className="interstitial">
|
||||
|
||||
Reference in New Issue
Block a user