sanitize all user inputs, fix #2172

This commit is contained in:
Amruth Pillai
2025-01-24 23:53:45 +01:00
parent 308a8e3ae3
commit c7ae0e94d7
29 changed files with 190 additions and 99 deletions

View File

@ -7,9 +7,10 @@ import { useMemo } from "react";
type Props = {
size?: number;
className?: string;
};
export const ThemeSwitch = ({ size = 20 }: Props) => {
export const ThemeSwitch = ({ size = 20, className }: Props) => {
const { theme, toggleTheme } = useTheme();
const variants: Variants = useMemo(() => {
@ -21,7 +22,7 @@ export const ThemeSwitch = ({ size = 20 }: Props) => {
}, [size]);
return (
<Button size="icon" variant="ghost" onClick={toggleTheme}>
<Button size="icon" variant="ghost" className={className} onClick={toggleTheme}>
<div className="cursor-pointer overflow-hidden" style={{ width: size, height: size }}>
<motion.div animate={theme} variants={variants} className="flex">
<Sun size={size} className="shrink-0" />

View File

@ -18,12 +18,12 @@ export const BuilderPage = () => {
const title = useResumeStore((state) => state.resume.title);
const updateResumeInFrame = useCallback(() => {
if (!frameRef?.contentWindow) return;
const message = { type: "SET_RESUME", payload: resume.data };
(() => {
frameRef.contentWindow.postMessage(message, "*");
})();
}, [frameRef, resume.data]);
setImmediate(() => {
frameRef?.contentWindow?.postMessage(message, "*");
});
}, [frameRef?.contentWindow, resume.data]);
// Send resume data to iframe on initial load
useEffect(() => {

View File

@ -27,12 +27,12 @@ export const PublicResumePage = () => {
const format = resume.metadata.page.format as keyof typeof pageSizeMap;
const updateResumeInFrame = useCallback(() => {
if (!frameRef.current?.contentWindow) return;
const message = { type: "SET_RESUME", payload: resume };
(() => {
frameRef.current.contentWindow.postMessage(message, "*");
})();
}, [frameRef, resume]);
setImmediate(() => {
frameRef.current?.contentWindow?.postMessage(message, "*");
});
}, [frameRef.current, resume]);
useEffect(() => {
if (!frameRef.current) return;
@ -77,7 +77,7 @@ export const PublicResumePage = () => {
<div
style={{ width: `${pageSizeMap[format].width}mm` }}
className="overflow-hidden rounded shadow-xl sm:mx-auto sm:mb-6 sm:mt-16 print:m-0 print:shadow-none"
className="relative z-50 overflow-hidden rounded shadow-xl sm:mx-auto sm:mb-6 sm:mt-16 print:m-0 print:shadow-none"
>
<iframe
ref={frameRef}
@ -97,12 +97,10 @@ export const PublicResumePage = () => {
</Link>
</div>
<div className="fixed bottom-5 right-5 hidden sm:block print:hidden">
<div className="flex items-center gap-x-4">
<Button variant="outline" className="gap-x-2 rounded-full" onClick={onDownloadPdf}>
{loading ? <CircleNotch size={16} className="animate-spin" /> : <FilePdf size={16} />}
{/* eslint-disable-next-line lingui/no-unlocalized-strings */}
<span>{t`Download PDF`}</span>
<div className="fixed bottom-5 right-5 z-0 hidden sm:block print:hidden">
<div className="flex flex-col items-center gap-y-2">
<Button size="icon" variant="ghost" onClick={onDownloadPdf}>
{loading ? <CircleNotch size={20} className="animate-spin" /> : <FilePdf size={20} />}
</Button>
<ThemeSwitch />

View File

@ -22,8 +22,7 @@ import { GuestGuard } from "./guards/guest";
import { authLoader } from "./loaders/auth";
export const routes = createRoutesFromElements(
// eslint-disable-next-line lingui/no-unlocalized-strings
<Route element={<Providers />} hydrateFallbackElement={<div>Loading...</div>}>
<Route element={<Providers />}>
<Route element={<HomeLayout />}>
<Route path="/" element={<HomePage />} />
</Route>