fix(web): hand the new heartbeat token over in sessionStorage, not the URL
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { api, Incident, Rollup } from "@/lib/api";
|
||||
import { Button, ConfirmDialog, friendlyMessage, useToast } from "@/components/ui";
|
||||
@@ -322,7 +322,6 @@ function Row({ label, value }: { label: string; value: React.ReactNode }) {
|
||||
export default function MonitorDetailPage() {
|
||||
const params = useParams();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const queryClient = useQueryClient();
|
||||
const monitorId = params.id as string;
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
@@ -330,19 +329,21 @@ export default function MonitorDetailPage() {
|
||||
const [range, setRange] = useState<Range>(RANGES[0]);
|
||||
const toast = useToast();
|
||||
|
||||
/* The token is only ever handed back once, on the create response, riding
|
||||
in the query string for this one navigation. Keep it in state and strip
|
||||
the query immediately so a reload, a bookmark or browser history never
|
||||
holds it. */
|
||||
/* The token is only ever handed back once, on the create response. The
|
||||
create page parks it in sessionStorage for this one navigation, because a
|
||||
query string would reach proxy access logs. Read it once and remove it
|
||||
straight away so a reload or another tab never shows it again. */
|
||||
const [heartbeatToken, setHeartbeatToken] = useState<string | null>(null);
|
||||
useEffect(() => {
|
||||
const t = searchParams.get("token");
|
||||
if (t) {
|
||||
setHeartbeatToken(t);
|
||||
router.replace(`/monitors/${monitorId}`);
|
||||
const key = `vantage:hbtoken:${monitorId}`;
|
||||
try {
|
||||
const t = sessionStorage.getItem(key);
|
||||
sessionStorage.removeItem(key);
|
||||
if (t) setHeartbeatToken(t);
|
||||
} catch {
|
||||
// Storage blocked: nothing was handed over.
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [monitorId]);
|
||||
|
||||
const { data: monitor, isLoading } = useQuery({
|
||||
queryKey: ["monitors", monitorId],
|
||||
|
||||
@@ -24,11 +24,16 @@ export default function NewMonitorPage() {
|
||||
// survive the route change, which is the one thing an inline
|
||||
// banner on the form cannot do. The error stays on the form.
|
||||
toast.success(`Created ${m.name}. First check runs within its interval.`);
|
||||
// The token is shown once. Hand it over in memory, never in the
|
||||
// URL: the RSC fetch for a query string lands in proxy access logs.
|
||||
if (m.heartbeat_token) {
|
||||
router.push(`/monitors/${m.monitor_id}?token=${encodeURIComponent(m.heartbeat_token)}`);
|
||||
} else {
|
||||
router.push(`/monitors/${m.monitor_id}`);
|
||||
try {
|
||||
sessionStorage.setItem(`vantage:hbtoken:${m.monitor_id}`, m.heartbeat_token);
|
||||
} catch {
|
||||
// Storage blocked: the user can rotate to get a token.
|
||||
}
|
||||
}
|
||||
router.push(`/monitors/${m.monitor_id}`);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user