Compare commits

..

No commits in common. "136f41020f1f78003cd78e45749eeb97916b5f4d" and "5b8643a9e7ae090d9783bbe747685609d0738ee1" have entirely different histories.

2 changed files with 16 additions and 40 deletions

View File

@ -211,13 +211,6 @@ function LoginForm() {
<p className={`text-sm font-medium text-center ${isError ? "text-red-600 dark:text-red-400" : "text-foreground"}`}>{status}</p> <p className={`text-sm font-medium text-center ${isError ? "text-red-600 dark:text-red-400" : "text-foreground"}`}>{status}</p>
</div> </div>
)} )}
<p className="text-center text-sm text-muted-foreground">
Don&rsquo;t have an account?{" "}
<Link href="/register" className="font-semibold text-primary hover:underline">
Sign up
</Link>
</p>
</form> </form>
); );
} }
@ -260,8 +253,7 @@ export default function LoginPage() {
Sign In Sign In
</h2> </h2>
<p className="mt-2 text-center text-sm text-muted-foreground"> <p className="mt-2 text-center text-sm text-muted-foreground">
New to Aarthalabs?{" "} <Link href="/register" className="font-medium text-primary hover:text-primary/80 transition-colors">
<Link href="/register" className="font-semibold text-primary hover:underline">
Start your 14-day free trial Start your 14-day free trial
</Link> </Link>
</p> </p>

View File

@ -34,41 +34,25 @@ export function clearAuth(): void {
localStorage.removeItem(USER_KEY); localStorage.removeItem(USER_KEY);
} }
// Shared in-flight refresh promise so concurrent 401s (e.g. several widgets
// loading at once) all await the same refresh call instead of each firing
// their own — refresh tokens are single-use, so racing calls would otherwise
// invalidate each other and force a false session-expired logout.
let refreshInFlight: Promise<boolean> | null = null;
async function tryRefresh(): Promise<boolean> { async function tryRefresh(): Promise<boolean> {
if (refreshInFlight) return refreshInFlight; try {
const res = await fetch("/api/auth/refresh", {
refreshInFlight = (async () => { method: "POST",
try { headers: { "Content-Type": "application/json" },
const res = await fetch("/api/auth/refresh", { });
method: "POST", if (!res.ok) {
headers: { "Content-Type": "application/json" },
});
if (!res.ok) {
clearAuth();
return false;
}
const payload = (await res.json()) as ApiResponse<unknown>;
if (payload.error) {
clearAuth();
return false;
}
return true;
} catch {
clearAuth(); clearAuth();
return false; return false;
} }
})(); const payload = (await res.json()) as ApiResponse<unknown>;
if (payload.error) {
try { clearAuth();
return await refreshInFlight; return false;
} finally { }
refreshInFlight = null; return true;
} catch {
clearAuth();
return false;
} }
} }