feat(auth): unify sign-in options

This commit is contained in:
cesnimda
2026-08-09 16:07:33 +02:00
parent 83ddc0718e
commit 93b869259e
5 changed files with 200 additions and 49 deletions
@@ -32,7 +32,7 @@ export function getMicrosoftMsalInstance(clientId: string): PublicClientApplicat
return msalInstance;
}
export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => void }) {
export default function MicrosoftAuthCard({ onSignedIn, presentation = "account" }: { onSignedIn?: () => void; presentation?: "account" | "sign-in" }) {
const { toast } = useToast();
const { t } = useI18n();
const [me, setMe] = useState<MeResponse | null>(null);
@@ -41,8 +41,9 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
const [currentPassword, setCurrentPassword] = useState("");
const clientId = (process.env.NEXT_PUBLIC_MICROSOFT_CLIENT_ID || "").trim();
const signInOnly = presentation === "sign-in";
const signedIn = Boolean(me?.provider);
const actionLabel = !signedIn
const actionLabel = signInOnly || !signedIn
? t("continueWithMicrosoft")
: me?.provider === "local" && !me?.microsoftLink?.linked
? t("linkWithMicrosoft")
@@ -58,14 +59,16 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
}
useEffect(() => {
if (signInOnly) return;
void refreshMe();
}, []);
}, [signInOnly]);
useEffect(() => {
if (signInOnly) return;
const onAuthChanged = () => { void refreshMe(); };
window.addEventListener("auth-changed", onAuthChanged);
return () => window.removeEventListener("auth-changed", onAuthChanged);
}, []);
}, [signInOnly]);
async function handleSignIn() {
if (!clientId) return;
@@ -77,7 +80,7 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
const idToken = result.idToken;
if (!idToken) throw new Error(t("microsoftAuthFailed"));
if (me?.provider === "local") {
if (!signInOnly && me?.provider === "local") {
const res = await api.post<{ linked: boolean; email?: string | null }>("/auth/microsoft/link", { token: idToken, currentPassword });
toast(res.data?.email ? t("microsoftLinkedSuccessWithEmail", { email: res.data.email }) : t("microsoftLinkedSuccess"), "success");
clearAuthClientState();
@@ -107,6 +110,23 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
const signedInName = me?.userName || me?.displayName || [me?.firstName, me?.lastName].filter(Boolean).join(" ") || me?.email || "";
if (signInOnly) {
if (pendingToken) {
return <TwoFactorChallenge
pendingToken={pendingToken}
onCancel={() => setPendingToken(null)}
onSuccess={() => {
setPendingToken(null);
window.dispatchEvent(new Event("auth-changed"));
toast(t("microsoftSignedIn"), "success");
onSignedIn?.();
}}
/>;
}
return <Button fullWidth variant="outlined" disabled={working || !clientId} onClick={() => void handleSignIn()}>{actionLabel}</Button>;
}
return (
<Paper sx={{ mt: 2, p: 2 }}>
<Typography variant="h6" sx={{ mb: 1 }}>