diff --git a/surfsense_backend/.env.example b/surfsense_backend/.env.example index 63b49639c..4a47542aa 100644 --- a/surfsense_backend/.env.example +++ b/surfsense_backend/.env.example @@ -28,6 +28,10 @@ NEXT_FRONTEND_URL=http://localhost:3000 AUTH_TYPE=LOCAL REGISTRATION_ENABLED=TRUE or FALSE +# CORS Configuration (comma-separated list of allowed origins) +# Use * to allow all origins, or specify domains like: https://example.com,https://app.example.com +CORS_ORIGINS=* + # Google OAuth Credentials (OPTIONAL - Required only for Gmail and Google Calendar connectors) GOOGLE_OAUTH_CLIENT_ID=your_google_client_id GOOGLE_OAUTH_CLIENT_SECRET=your_google_client_secret diff --git a/surfsense_backend/app/app.py b/surfsense_backend/app/app.py index ed0269bed..231f99e46 100644 --- a/surfsense_backend/app/app.py +++ b/surfsense_backend/app/app.py @@ -50,7 +50,7 @@ app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*") # Add CORS middleware app.add_middleware( CORSMiddleware, - allow_origins=["https://ai.kapteinis.lv"], # Only allow our domain + allow_origins=config.CORS_ORIGINS, # Configurable via CORS_ORIGINS env var allow_credentials=True, allow_methods=["*"], # Allows all methods allow_headers=["*"], # Allows all headers diff --git a/surfsense_backend/app/config/__init__.py b/surfsense_backend/app/config/__init__.py index 7d06643e1..df2744f4d 100644 --- a/surfsense_backend/app/config/__init__.py +++ b/surfsense_backend/app/config/__init__.py @@ -135,6 +135,11 @@ class Config: AUTH_TYPE = os.getenv("AUTH_TYPE") REGISTRATION_ENABLED = os.getenv("REGISTRATION_ENABLED", "TRUE").upper() == "TRUE" + # CORS Configuration + # Comma-separated list of allowed origins, defaults to all origins if not set + _cors_origins_str = os.getenv("CORS_ORIGINS", "*") + CORS_ORIGINS = [origin.strip() for origin in _cors_origins_str.split(",") if origin.strip()] + # Google OAuth GOOGLE_OAUTH_CLIENT_ID = os.getenv("GOOGLE_OAUTH_CLIENT_ID") GOOGLE_OAUTH_CLIENT_SECRET = os.getenv("GOOGLE_OAUTH_CLIENT_SECRET") diff --git a/surfsense_web/app/auth/callback/page.tsx b/surfsense_web/app/auth/callback/page.tsx index da868c316..0589df374 100644 --- a/surfsense_web/app/auth/callback/page.tsx +++ b/surfsense_web/app/auth/callback/page.tsx @@ -1,5 +1,6 @@ import { Suspense } from "react"; import TokenHandler from "@/components/TokenHandler"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export default function AuthCallbackPage() { return ( @@ -15,7 +16,7 @@ export default function AuthCallbackPage() { diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/airtable-connector/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/airtable-connector/page.tsx index 2d82877b3..bf22572be 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/airtable-connector/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/airtable-connector/page.tsx @@ -22,6 +22,7 @@ import { type SearchSourceConnector, useSearchSourceConnectors, } from "@/hooks/use-search-source-connectors"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export default function AirtableConnectorPage() { const router = useRouter(); @@ -51,7 +52,7 @@ export default function AirtableConnectorPage() { { method: "GET", headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/github-connector/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/github-connector/page.tsx index 90a02a5f2..536db22c8 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/github-connector/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/github-connector/page.tsx @@ -38,6 +38,7 @@ import { Input } from "@/components/ui/input"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { EnumConnectorName } from "@/contracts/enums/connector"; import { getConnectorIcon } from "@/contracts/enums/connectorIcons"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; // Assuming useSearchSourceConnectors hook exists and works similarly import { useSearchSourceConnectors } from "@/hooks/use-search-source-connectors"; @@ -101,7 +102,7 @@ export default function GithubConnectorPage() { setConnectorName(values.name); // Store the name setValidatedPat(values.github_pat); // Store the PAT temporarily try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); } diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-calendar-connector/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-calendar-connector/page.tsx index 2fdc95671..b7a45db39 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-calendar-connector/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-calendar-connector/page.tsx @@ -24,6 +24,7 @@ import { type SearchSourceConnector, useSearchSourceConnectors, } from "@/hooks/use-search-source-connectors"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export default function GoogleCalendarConnectorPage() { const router = useRouter(); @@ -56,7 +57,7 @@ export default function GoogleCalendarConnectorPage() { { method: "GET", headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx index c1354d03e..88856a200 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx @@ -24,6 +24,7 @@ import { type SearchSourceConnector, useSearchSourceConnectors, } from "@/hooks/use-search-source-connectors"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export default function GoogleGmailConnectorPage() { const router = useRouter(); @@ -55,7 +56,7 @@ export default function GoogleGmailConnectorPage() { { method: "GET", headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); diff --git a/surfsense_web/app/dashboard/[search_space_id]/documents/webpage/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/documents/webpage/page.tsx index 0f78bad7c..9da3ad927 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/documents/webpage/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/documents/webpage/page.tsx @@ -16,6 +16,7 @@ import { CardTitle, } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; // URL validation regex - updated to support percent-encoded URLs (e.g., Latvian characters) const urlRegex = /^https?:\/\/[^\s]+$/; @@ -69,7 +70,7 @@ export default function WebpageCrawler() { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify({ document_type: "CRAWLED_URL", diff --git a/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx index 099909515..8d5bb6c8f 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/onboard/page.tsx @@ -12,6 +12,7 @@ import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import { useGlobalLLMConfigs, useLLMConfigs, useLLMPreferences } from "@/hooks/use-llm-configs"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; const TOTAL_STEPS = 2; @@ -38,7 +39,7 @@ const OnboardPage = () => { // Check if user is authenticated useEffect(() => { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { router.push("/login"); return; diff --git a/surfsense_web/app/dashboard/layout.tsx b/surfsense_web/app/dashboard/layout.tsx index bafe7a0cc..0f3b0ddb0 100644 --- a/surfsense_web/app/dashboard/layout.tsx +++ b/surfsense_web/app/dashboard/layout.tsx @@ -6,6 +6,7 @@ import { useEffect, useState } from "react"; import { AnnouncementBanner } from "@/components/announcement-banner"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { baseApiService } from "@/lib/apis/base-api.service"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface DashboardLayoutProps { children: React.ReactNode; @@ -17,7 +18,7 @@ export default function DashboardLayout({ children }: DashboardLayoutProps) { useEffect(() => { // Check if user is authenticated - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { router.push("/login"); return; diff --git a/surfsense_web/app/dashboard/page.tsx b/surfsense_web/app/dashboard/page.tsx index d61e714c6..a2fb4bd4f 100644 --- a/surfsense_web/app/dashboard/page.tsx +++ b/surfsense_web/app/dashboard/page.tsx @@ -35,6 +35,7 @@ import { Spotlight } from "@/components/ui/spotlight"; import { Tilt } from "@/components/ui/tilt"; import { useUser } from "@/hooks"; import { useSearchSpaces } from "@/hooks/use-search-spaces"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; /** * Formats a date string into a readable format @@ -177,7 +178,7 @@ const DashboardPage = () => { { method: "DELETE", headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); diff --git a/surfsense_web/app/dashboard/searchspaces/page.tsx b/surfsense_web/app/dashboard/searchspaces/page.tsx index 598536c1b..5fa916266 100644 --- a/surfsense_web/app/dashboard/searchspaces/page.tsx +++ b/surfsense_web/app/dashboard/searchspaces/page.tsx @@ -4,6 +4,7 @@ import { motion } from "motion/react"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { SearchSpaceForm } from "@/components/search-space-form"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export default function SearchSpacesPage() { const router = useRouter(); const handleCreateSearchSpace = async (data: { name: string; description: string }) => { @@ -14,7 +15,7 @@ export default function SearchSpacesPage() { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify(data), } diff --git a/surfsense_web/app/dashboard/site-settings/page.tsx b/surfsense_web/app/dashboard/site-settings/page.tsx index 7cb2497bd..7a9b63925 100644 --- a/surfsense_web/app/dashboard/site-settings/page.tsx +++ b/surfsense_web/app/dashboard/site-settings/page.tsx @@ -6,6 +6,7 @@ import { toast } from "sonner"; import { useSiteConfig } from "@/contexts/SiteConfigContext"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Loader2 } from "lucide-react"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface SiteConfigForm { // Header/Navbar toggles @@ -67,7 +68,7 @@ export default function SiteSettingsPage() { const checkSuperuser = async () => { try { const backendUrl = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "http://localhost:8000"; - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { router.push("/login"); @@ -150,7 +151,7 @@ export default function SiteSettingsPage() { setIsSaving(true); try { const backendUrl = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "http://localhost:8000"; - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); const response = await fetch(`${backendUrl}/api/v1/site-config`, { method: "PUT", diff --git a/surfsense_web/atoms/chats/chat-mutation.atoms.ts b/surfsense_web/atoms/chats/chat-mutation.atoms.ts index da0795afa..f9d4ba50a 100644 --- a/surfsense_web/atoms/chats/chat-mutation.atoms.ts +++ b/surfsense_web/atoms/chats/chat-mutation.atoms.ts @@ -2,13 +2,14 @@ import { atomWithMutation } from "jotai-tanstack-query"; import { toast } from "sonner"; import type { Chat } from "@/app/dashboard/[search_space_id]/chats/chats-client"; import { chatApiService } from "@/lib/apis/chats-api.service"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; import { cacheKeys } from "@/lib/query-client/cache-keys"; import { queryClient } from "@/lib/query-client/client"; import { activeSearchSpaceIdAtom } from "../seach-spaces/seach-space-queries.atom"; export const deleteChatMutationAtom = atomWithMutation((get) => { const searchSpaceId = get(activeSearchSpaceIdAtom); - const authToken = localStorage.getItem("surfsense_bearer_token"); + const authToken = localStorage.getItem(AUTH_TOKEN_KEY); return { mutationKey: cacheKeys.activeSearchSpace.chats(searchSpaceId ?? ""), diff --git a/surfsense_web/atoms/chats/chat-querie.atoms.ts b/surfsense_web/atoms/chats/chat-querie.atoms.ts index 8ea668eb4..28a58de93 100644 --- a/surfsense_web/atoms/chats/chat-querie.atoms.ts +++ b/surfsense_web/atoms/chats/chat-querie.atoms.ts @@ -4,6 +4,7 @@ import type { ChatDetails } from "@/app/dashboard/[search_space_id]/chats/chats- import type { PodcastItem } from "@/app/dashboard/[search_space_id]/podcasts/podcasts-client"; import { activeSearchSpaceIdAtom } from "@/atoms/seach-spaces/seach-space-queries.atom"; import { chatApiService } from "@/lib/apis/chats-api.service"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; import { getPodcastByChatId } from "@/lib/apis/podcasts.api"; import { cacheKeys } from "@/lib/query-client/cache-keys"; @@ -17,7 +18,7 @@ export const activeChatIdAtom = atom(null); export const activeChatAtom = atomWithQuery((get) => { const activeChatId = get(activeChatIdAtom); - const authToken = localStorage.getItem("surfsense_bearer_token"); + const authToken = localStorage.getItem(AUTH_TOKEN_KEY); return { queryKey: cacheKeys.activeSearchSpace.activeChat(activeChatId ?? ""), @@ -42,7 +43,7 @@ export const activeChatAtom = atomWithQuery((get) => { export const activeSearchSpaceChatsAtom = atomWithQuery((get) => { const searchSpaceId = get(activeSearchSpaceIdAtom); - const authToken = localStorage.getItem("surfsense_bearer_token"); + const authToken = localStorage.getItem(AUTH_TOKEN_KEY); return { queryKey: cacheKeys.activeSearchSpace.chats(searchSpaceId ?? ""), diff --git a/surfsense_web/components/TokenHandler.tsx b/surfsense_web/components/TokenHandler.tsx index fd9924b3d..e4c7d6672 100644 --- a/surfsense_web/components/TokenHandler.tsx +++ b/surfsense_web/components/TokenHandler.tsx @@ -3,6 +3,7 @@ import { useRouter, useSearchParams } from "next/navigation"; import { useEffect } from "react"; import { baseApiService } from "@/lib/apis/base-api.service"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface TokenHandlerProps { redirectPath?: string; // Path to redirect after storing token @@ -20,7 +21,7 @@ interface TokenHandlerProps { const TokenHandler = ({ redirectPath = "/", tokenParamName = "token", - storageKey = "surfsense_bearer_token", + storageKey = AUTH_TOKEN_KEY, }: TokenHandlerProps) => { const router = useRouter(); const searchParams = useSearchParams(); diff --git a/surfsense_web/components/UserDropdown.tsx b/surfsense_web/components/UserDropdown.tsx index c0f333019..7afec5687 100644 --- a/surfsense_web/components/UserDropdown.tsx +++ b/surfsense_web/components/UserDropdown.tsx @@ -4,6 +4,7 @@ import { BadgeCheck, LogOut, Settings } from "lucide-react"; import { useRouter } from "next/navigation"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { baseApiService } from "@/lib/apis/base-api.service"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; import { Button } from "@/components/ui/button"; import { DropdownMenu, @@ -29,7 +30,7 @@ export function UserDropdown({ const handleLogout = () => { try { if (typeof window !== "undefined") { - localStorage.removeItem("surfsense_bearer_token"); + localStorage.removeItem(AUTH_TOKEN_KEY); // Clear the baseApiService token to prevent stale auth state baseApiService.setBearerToken(""); router.push("/"); diff --git a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx index 3edd00400..082955a0a 100644 --- a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx +++ b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx @@ -7,6 +7,7 @@ import { activeChathatUIAtom } from "@/atoms/chats/ui.atoms"; import { generatePodcast } from "@/lib/apis/podcasts.api"; import { cn } from "@/lib/utils"; import { ChatPanelView } from "./ChatPanelView"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export interface GeneratePodcastRequest { type: "CHAT" | "DOCUMENT"; @@ -23,7 +24,7 @@ export function ChatPanelContainer() { error: chatError, } = useAtomValue(activeChatAtom); const activeChatIdState = useAtomValue(activeChatIdAtom); - const authToken = localStorage.getItem("surfsense_bearer_token"); + const authToken = localStorage.getItem(AUTH_TOKEN_KEY); const { isChatPannelOpen } = useAtomValue(activeChathatUIAtom); const handleGeneratePodcast = async (request: GeneratePodcastRequest) => { diff --git a/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx b/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx index f789ab848..206deef6e 100644 --- a/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx +++ b/surfsense_web/components/chat/ChatPanel/PodcastPlayer/PodcastPlayer.tsx @@ -8,6 +8,7 @@ import type { PodcastItem } from "@/app/dashboard/[search_space_id]/podcasts/pod import { Button } from "@/components/ui/button"; import { Slider } from "@/components/ui/slider"; import { PodcastPlayerCompactSkeleton } from "./PodcastPlayerCompactSkeleton"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface PodcastPlayerProps { podcast: PodcastItem | null; @@ -56,7 +57,7 @@ export function PodcastPlayer({ const loadPodcast = async () => { setIsFetching(true); try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("Authentication token not found."); } diff --git a/surfsense_web/components/sources/DocumentUploadTab.tsx b/surfsense_web/components/sources/DocumentUploadTab.tsx index c9976bb64..857516ebe 100644 --- a/surfsense_web/components/sources/DocumentUploadTab.tsx +++ b/surfsense_web/components/sources/DocumentUploadTab.tsx @@ -15,6 +15,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com import { Progress } from "@/components/ui/progress"; import { Separator } from "@/components/ui/separator"; import { GridPattern } from "./GridPattern"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface DocumentUploadTabProps { searchSpaceId: string; @@ -169,7 +170,7 @@ export function DocumentUploadTab({ searchSpaceId }: DocumentUploadTabProps) { { method: "POST", headers: { - Authorization: `Bearer ${window.localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${window.localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: formData, } diff --git a/surfsense_web/components/sources/YouTubeTab.tsx b/surfsense_web/components/sources/YouTubeTab.tsx index 717a4266d..53972f971 100644 --- a/surfsense_web/components/sources/YouTubeTab.tsx +++ b/surfsense_web/components/sources/YouTubeTab.tsx @@ -19,6 +19,7 @@ import { CardTitle, } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; const youtubeRegex = /^(https:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})$/; @@ -72,7 +73,7 @@ export function YouTubeTab({ searchSpaceId }: YouTubeTabProps) { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify({ document_type: "YOUTUBE_VIDEO", diff --git a/surfsense_web/hooks/use-api-key.ts b/surfsense_web/hooks/use-api-key.ts index 229a8de3e..0045ced6f 100644 --- a/surfsense_web/hooks/use-api-key.ts +++ b/surfsense_web/hooks/use-api-key.ts @@ -1,5 +1,6 @@ import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface UseApiKeyReturn { apiKey: string | null; @@ -17,7 +18,7 @@ export function useApiKey(): UseApiKeyReturn { // Load API key from localStorage const loadApiKey = () => { try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); setApiKey(token); } catch (error) { console.error("Error loading API key:", error); diff --git a/surfsense_web/hooks/use-chat.ts b/surfsense_web/hooks/use-chat.ts index a3462203a..9d6728702 100644 --- a/surfsense_web/hooks/use-chat.ts +++ b/surfsense_web/hooks/use-chat.ts @@ -3,6 +3,7 @@ import { useCallback, useEffect, useState } from "react"; import type { ChatDetails } from "@/app/dashboard/[search_space_id]/chats/chats-client"; import type { ResearchMode } from "@/components/chat"; import type { Document } from "@/hooks/use-documents"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface UseChatStateProps { search_space_id: string; @@ -22,7 +23,7 @@ export function useChatState({ chat_id }: UseChatStateProps) { const [topK, setTopK] = useState(5); useEffect(() => { - const bearerToken = localStorage.getItem("surfsense_bearer_token"); + const bearerToken = localStorage.getItem(AUTH_TOKEN_KEY); setToken(bearerToken); }, []); diff --git a/surfsense_web/hooks/use-connector-edit-page.ts b/surfsense_web/hooks/use-connector-edit-page.ts index 870a87dcb..ef45828ce 100644 --- a/surfsense_web/hooks/use-connector-edit-page.ts +++ b/surfsense_web/hooks/use-connector-edit-page.ts @@ -15,6 +15,7 @@ import { type SearchSourceConnector, useSearchSourceConnectors, } from "@/hooks/use-search-source-connectors"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; const normalizeListInput = (value: unknown): string[] => { if (Array.isArray(value)) { @@ -174,7 +175,7 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string) setIsFetchingRepos(true); setFetchedRepos(null); try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) throw new Error("No auth token"); const response = await fetch( `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/github/repositories`, diff --git a/surfsense_web/hooks/use-connectors.ts b/surfsense_web/hooks/use-connectors.ts index db0a2618e..f1d43353c 100644 --- a/surfsense_web/hooks/use-connectors.ts +++ b/surfsense_web/hooks/use-connectors.ts @@ -1,3 +1,5 @@ +import { AUTH_TOKEN_KEY } from "@/lib/constants"; + // Types for connector API export interface ConnectorConfig { [key: string]: string; @@ -38,7 +40,7 @@ export const ConnectorService = { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify(data), } @@ -58,7 +60,7 @@ export const ConnectorService = { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors?skip=${skip}&limit=${limit}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); @@ -77,7 +79,7 @@ export const ConnectorService = { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors/${connectorId}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); @@ -98,7 +100,7 @@ export const ConnectorService = { method: "PUT", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify(data), } @@ -119,7 +121,7 @@ export const ConnectorService = { { method: "DELETE", headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); diff --git a/surfsense_web/hooks/use-document-by-chunk.ts b/surfsense_web/hooks/use-document-by-chunk.ts index dd36fcab1..be84b0375 100644 --- a/surfsense_web/hooks/use-document-by-chunk.ts +++ b/surfsense_web/hooks/use-document-by-chunk.ts @@ -1,6 +1,7 @@ "use client"; import { useCallback, useState } from "react"; import { toast } from "sonner"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export interface Chunk { id: number; @@ -53,7 +54,7 @@ export function useDocumentByChunk() { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/by-chunk/${chunkId}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, "Content-Type": "application/json", }, method: "GET", diff --git a/surfsense_web/hooks/use-document-types.ts b/surfsense_web/hooks/use-document-types.ts index 415e42e90..52c873a5b 100644 --- a/surfsense_web/hooks/use-document-types.ts +++ b/surfsense_web/hooks/use-document-types.ts @@ -1,4 +1,5 @@ import { useCallback, useEffect, useState } from "react"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export interface DocumentTypeCount { type: string; @@ -23,7 +24,7 @@ export const useDocumentTypes = (searchSpaceId?: number, lazy: boolean = false) try { setIsLoading(true); setError(null); - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); diff --git a/surfsense_web/hooks/use-documents.ts b/surfsense_web/hooks/use-documents.ts index 21ee959b8..53d13e10e 100644 --- a/surfsense_web/hooks/use-documents.ts +++ b/surfsense_web/hooks/use-documents.ts @@ -2,6 +2,7 @@ import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; import { normalizeListResponse } from "@/lib/pagination"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export interface Document { id: number; @@ -82,7 +83,7 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents?${params.toString()}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -163,7 +164,7 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/search?${params.toString()}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -197,7 +198,7 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/${documentId}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "DELETE", } @@ -232,7 +233,7 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/type-counts?${params.toString()}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } diff --git a/surfsense_web/hooks/use-llm-configs.ts b/surfsense_web/hooks/use-llm-configs.ts index 0755211c4..c6ec4838e 100644 --- a/surfsense_web/hooks/use-llm-configs.ts +++ b/surfsense_web/hooks/use-llm-configs.ts @@ -1,6 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import { toast } from "sonner"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export interface LLMConfig { id: number; @@ -65,7 +66,7 @@ export function useLLMConfigs(searchSpaceId: number | null) { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/llm-configs?search_space_id=${searchSpaceId}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -98,7 +99,7 @@ export function useLLMConfigs(searchSpaceId: number | null) { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify(config), } @@ -127,7 +128,7 @@ export function useLLMConfigs(searchSpaceId: number | null) { { method: "DELETE", headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, } ); @@ -157,7 +158,7 @@ export function useLLMConfigs(searchSpaceId: number | null) { method: "PUT", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify(config), } @@ -207,7 +208,7 @@ export function useLLMPreferences(searchSpaceId: number | null) { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-spaces/${searchSpaceId}/llm-preferences`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -245,7 +246,7 @@ export function useLLMPreferences(searchSpaceId: number | null) { method: "PUT", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, body: JSON.stringify(newPreferences), } @@ -297,7 +298,7 @@ export function useGlobalLLMConfigs() { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/global-llm-configs`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } diff --git a/surfsense_web/hooks/use-logs.ts b/surfsense_web/hooks/use-logs.ts index 7defd8345..4823f62c6 100644 --- a/surfsense_web/hooks/use-logs.ts +++ b/surfsense_web/hooks/use-logs.ts @@ -1,6 +1,7 @@ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { toast } from "sonner"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export type LogLevel = "DEBUG" | "INFO" | "WARNING" | "ERROR" | "CRITICAL"; export type LogStatus = "IN_PROGRESS" | "SUCCESS" | "FAILED"; @@ -99,7 +100,7 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs?${params}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -150,7 +151,7 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) { const response = await fetch(`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs`, { headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "POST", body: JSON.stringify(logData), @@ -184,7 +185,7 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) { { headers: { "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "PUT", body: JSON.stringify(updateData), @@ -216,7 +217,7 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/${logId}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "DELETE", } @@ -244,7 +245,7 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/${logId}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -291,7 +292,7 @@ export function useLogsSummary(searchSpaceId: number, hours: number = 24) { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/search-space/${searchSpaceId}/summary?hours=${hours}`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } diff --git a/surfsense_web/hooks/use-search-source-connectors.ts b/surfsense_web/hooks/use-search-source-connectors.ts index 41b5f5115..22f707e39 100644 --- a/surfsense_web/hooks/use-search-source-connectors.ts +++ b/surfsense_web/hooks/use-search-source-connectors.ts @@ -1,4 +1,5 @@ import { useCallback, useEffect, useState } from "react"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; export interface SearchSourceConnector { id: number; @@ -66,7 +67,7 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?: try { setIsLoading(true); setError(null); - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); @@ -176,7 +177,7 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?: spaceId: number ) => { try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); @@ -222,7 +223,7 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?: > ) => { try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); @@ -262,7 +263,7 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?: */ const deleteConnector = async (connectorId: number) => { try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); @@ -302,7 +303,7 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?: endDate?: string ) => { try { - const token = localStorage.getItem("surfsense_bearer_token"); + const token = localStorage.getItem(AUTH_TOKEN_KEY); if (!token) { throw new Error("No authentication token found"); diff --git a/surfsense_web/hooks/use-search-spaces.ts b/surfsense_web/hooks/use-search-spaces.ts index 43c34fbd9..daec2542c 100644 --- a/surfsense_web/hooks/use-search-spaces.ts +++ b/surfsense_web/hooks/use-search-spaces.ts @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import { toast } from "sonner"; +import { AUTH_TOKEN_KEY } from "@/lib/constants"; interface SearchSpace { id: number; @@ -24,7 +25,7 @@ export function useSearchSpaces() { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", } @@ -57,7 +58,7 @@ export function useSearchSpaces() { `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces`, { headers: { - Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN_KEY)}`, }, method: "GET", }