diff --git a/apps/web/features/auth/auth-cookie.ts b/apps/web/features/auth/auth-cookie.ts new file mode 100644 index 00000000..4ec51928 --- /dev/null +++ b/apps/web/features/auth/auth-cookie.ts @@ -0,0 +1,9 @@ +const COOKIE_NAME = "multica_logged_in"; + +export function setLoggedInCookie() { + document.cookie = `${COOKIE_NAME}=1; path=/; max-age=31536000; samesite=lax`; +} + +export function clearLoggedInCookie() { + document.cookie = `${COOKIE_NAME}=; path=/; max-age=0`; +} diff --git a/apps/web/features/auth/initializer.tsx b/apps/web/features/auth/initializer.tsx index ffb0b87a..5f6f85a5 100644 --- a/apps/web/features/auth/initializer.tsx +++ b/apps/web/features/auth/initializer.tsx @@ -5,6 +5,7 @@ import { useAuthStore } from "./store"; import { useWorkspaceStore } from "@/features/workspace"; import { api } from "@/shared/api"; import { createLogger } from "@/shared/logger"; +import { setLoggedInCookie, clearLoggedInCookie } from "./auth-cookie"; const logger = createLogger("auth"); @@ -16,6 +17,7 @@ export function AuthInitializer({ children }: { children: ReactNode }) { useEffect(() => { const token = localStorage.getItem("multica_token"); if (!token) { + clearLoggedInCookie(); useAuthStore.setState({ isLoading: false }); return; } @@ -29,6 +31,7 @@ export function AuthInitializer({ children }: { children: ReactNode }) { Promise.all([mePromise, wsPromise]) .then(([user, wsList]) => { + setLoggedInCookie(); useAuthStore.setState({ user, isLoading: false }); useWorkspaceStore.getState().hydrateWorkspace(wsList, wsId); }) @@ -38,6 +41,7 @@ export function AuthInitializer({ children }: { children: ReactNode }) { api.setWorkspaceId(null); localStorage.removeItem("multica_token"); localStorage.removeItem("multica_workspace_id"); + clearLoggedInCookie(); useAuthStore.setState({ user: null, isLoading: false }); }); }, []); diff --git a/apps/web/features/auth/store.ts b/apps/web/features/auth/store.ts index 9957305e..3e99892f 100644 --- a/apps/web/features/auth/store.ts +++ b/apps/web/features/auth/store.ts @@ -3,6 +3,7 @@ import { create } from "zustand"; import type { User } from "@/shared/types"; import { api } from "@/shared/api"; +import { setLoggedInCookie, clearLoggedInCookie } from "./auth-cookie"; interface AuthState { user: User | null; @@ -48,6 +49,7 @@ export const useAuthStore = create((set) => ({ const { token, user } = await api.verifyCode(email, code); localStorage.setItem("multica_token", token); api.setToken(token); + setLoggedInCookie(); set({ user }); return user; }, @@ -57,6 +59,7 @@ export const useAuthStore = create((set) => ({ localStorage.removeItem("multica_workspace_id"); api.setToken(null); api.setWorkspaceId(null); + clearLoggedInCookie(); set({ user: null }); }, diff --git a/apps/web/proxy.ts b/apps/web/proxy.ts new file mode 100644 index 00000000..8e84c2b3 --- /dev/null +++ b/apps/web/proxy.ts @@ -0,0 +1,14 @@ +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +export function proxy(request: NextRequest) { + const loggedIn = request.cookies.has("multica_logged_in"); + if (loggedIn) { + return NextResponse.redirect(new URL("/issues", request.url)); + } + return NextResponse.next(); +} + +export const config = { + matcher: ["/"], +};