Merge pull request 'feat(auth): gate Google sign-in on CRM profile' (#11) from feat/login-methods into goutamnextflow
This commit was merged in pull request #11.
This commit is contained in:
@@ -24,8 +24,8 @@ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|||||||
|
|
||||||
export function LoginFlow() {
|
export function LoginFlow() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { login, loginWithOAuth, completeOAuthLogin } = useAuth();
|
const { login, loginWithOAuth, completeOAuthLogin, logout } = useAuth();
|
||||||
const { ready } = useAppShell();
|
const { ready, sdk } = useAppShell();
|
||||||
const [step, setStep] = useState<Step>("identify");
|
const [step, setStep] = useState<Step>("identify");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [account, setAccount] = useState<Account | null>(null);
|
const [account, setAccount] = useState<Account | null>(null);
|
||||||
@@ -76,20 +76,29 @@ export function LoginFlow() {
|
|||||||
if (!ready) { setStep("connecting"); return; }
|
if (!ready) { setStep("connecting"); return; }
|
||||||
setStep("connecting");
|
setStep("connecting");
|
||||||
completeOAuthLogin(code)
|
completeOAuthLogin(code)
|
||||||
.then((ace) => {
|
.then(async (ace) => {
|
||||||
if (ace) {
|
if (!ace) { replace("identify"); return; }
|
||||||
// Clear the ?code=… from the URL, then enter the app.
|
// Google is sign-IN only: require an existing CRM profile. If the account
|
||||||
window.history.replaceState({}, "", "/portal/login");
|
// has none, sign back out and show an error rather than silently admitting it.
|
||||||
router.replace("/dashboard");
|
let registered = false;
|
||||||
} else {
|
try {
|
||||||
|
const st = await sdk.query<{ registered: boolean }>("crm.account.registrationStatus");
|
||||||
|
registered = !!st?.registered;
|
||||||
|
} catch { registered = false; }
|
||||||
|
window.history.replaceState({}, "", "/portal/login");
|
||||||
|
if (!registered) {
|
||||||
|
try { await logout(); } catch { /* ignore */ }
|
||||||
|
setFlash("No account is registered for this Google email. Please register first.");
|
||||||
replace("identify");
|
replace("identify");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
router.replace("/dashboard");
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setFlash("Google sign-in didn't complete. Please try again.");
|
setFlash("Google sign-in didn't complete. Please try again.");
|
||||||
replace("identify");
|
replace("identify");
|
||||||
});
|
});
|
||||||
}, [ready, completeOAuthLogin, router]);
|
}, [ready, completeOAuthLogin, router, sdk, logout]);
|
||||||
|
|
||||||
/* ---- auth resolution ---- */
|
/* ---- auth resolution ---- */
|
||||||
function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") {
|
function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") {
|
||||||
@@ -144,7 +153,12 @@ export function LoginFlow() {
|
|||||||
/* =================================================================== */
|
/* =================================================================== */
|
||||||
return (
|
return (
|
||||||
<div className="card anim-fade-up" key={step}>
|
<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" && (
|
{step === "connecting" && (
|
||||||
<div className="interstitial">
|
<div className="interstitial">
|
||||||
|
|||||||
Reference in New Issue
Block a user