Skip to content

Commit a062cc8

Browse files
committed
fix(web): protect auth route from unauthenticated users
1 parent ccf5945 commit a062cc8

4 files changed

Lines changed: 31 additions & 18 deletions

File tree

apps/web/src/components/ui/header/index.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AnimatePresence, motion } from "motion/react";
2-
import { useState, useEffect } from "react";
2+
import { useState, useEffect, useMemo } from "react";
33
import { SearchIcon, XIcon } from "lucide-react";
44
import { cn } from "@/lib/utils";
55
import { Button } from "../button";
@@ -22,15 +22,25 @@ import { useSearch } from "@/lib/hooks";
2222
import type { GetApiV1SearchParams } from "@dester/api-client";
2323
import SearchResults from "./search-results";
2424
import { useLocation } from "@tanstack/react-router";
25+
import { useAuth } from "@/hooks/useAuth";
2526

26-
const tabs = [
27+
const allTabs = [
2728
{ id: "home", label: "Home", href: "/" },
2829
{ id: "library", label: "Library", href: "/library" },
2930
{ id: "settings", label: "Settings", href: "/settings" },
3031
];
3132

3233
const Header = () => {
3334
const location = useLocation();
35+
const { user } = useAuth();
36+
37+
// Filter tabs based on user role - hide Settings for guests and unauthenticated users
38+
const tabs = useMemo(() => {
39+
if (!user || user.role === "GUEST") {
40+
return allTabs.filter((tab) => tab.id !== "settings");
41+
}
42+
return allTabs;
43+
}, [user]);
3444
const [activeTab, setActiveTab] = useState(tabs[0].id);
3545
const [isSearchOpen, setIsSearchOpen] = useState(false);
3646
const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -52,7 +62,7 @@ const Header = () => {
5262
if (currentTab) {
5363
setActiveTab(currentTab.id);
5464
}
55-
}, [location.pathname]);
65+
}, [location.pathname, tabs]);
5666

5767
// Check if current path matches any of the header tabs
5868
const isOnHeaderTab = tabs.some((tab) => {

apps/web/src/components/ui/header/user-menu.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,19 @@ export default function UserMenu() {
9898

9999
{/* Menu Items */}
100100
<div className="py-1">
101-
<button
102-
onClick={() => {
103-
navigate({ to: "/settings" });
104-
setIsOpen(false);
105-
}}
106-
className="w-full px-4 py-2.5 text-left text-sm text-white hover:bg-white/10 transition-colors flex items-center gap-3"
107-
>
108-
<Settings className="w-4 h-4" />
109-
Settings
110-
</button>
101+
{/* Only show settings for non-guest users */}
102+
{user?.role !== "GUEST" && (
103+
<button
104+
onClick={() => {
105+
navigate({ to: "/settings" });
106+
setIsOpen(false);
107+
}}
108+
className="w-full px-4 py-2.5 text-left text-sm text-white hover:bg-white/10 transition-colors flex items-center gap-3"
109+
>
110+
<Settings className="w-4 h-4" />
111+
Settings
112+
</button>
113+
)}
111114

112115
<button
113116
onClick={() => {

apps/web/src/routes/settings/route.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import { useAuth } from "@/hooks/useAuth";
1010
export const Route = createFileRoute("/settings")({
1111
component: RouteComponent,
1212
beforeLoad: ({ location, context }) => {
13-
// Block guests from accessing settings
13+
// Block unauthenticated users and guests from accessing settings
1414
const user = (context as { auth?: { user?: { role?: string } } })?.auth
1515
?.user;
16-
if (user?.role === "GUEST") {
17-
throw redirect({ to: "/" });
16+
if (!user || user?.role === "GUEST") {
17+
throw redirect({ to: "/login" });
1818
}
1919

2020
// If we're at the exact settings route, redirect to libraries

apps/web/src/types/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface User {
66
id: string;
77
username: string;
88
email?: string;
9-
role: "USER" | "ADMIN";
9+
role: "USER" | "ADMIN" | "GUEST";
1010
createdAt: string;
1111
updatedAt: string;
1212
}
@@ -22,7 +22,7 @@ export interface RegisterData {
2222
email?: string;
2323
password?: string;
2424
pin?: string;
25-
role?: "USER" | "ADMIN";
25+
role?: "USER" | "ADMIN" | "GUEST";
2626
}
2727

2828
export interface AuthResponse {

0 commit comments

Comments
 (0)