mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-15 18:25:18 +02:00
refactor: centralize authentication handling
- Replaced direct localStorage token access with a centralized `getBearerToken` function across various components and hooks to improve code maintainability and security. - Updated API calls to use `authenticatedFetch` for consistent authentication handling. - Enhanced user experience by ensuring proper redirection to login when authentication fails. - Cleaned up unused imports and improved overall code structure for better readability.
This commit is contained in:
parent
6cc9e38e1d
commit
b2a97b39ce
35 changed files with 396 additions and 497 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { getBearerToken } from "@/lib/auth-utils";
|
||||
|
||||
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 = getBearerToken();
|
||||
setApiKey(token);
|
||||
} catch (error) {
|
||||
console.error("Error loading API key:", error);
|
||||
|
|
|
|||
|
|
@ -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 { getBearerToken } from "@/lib/auth-utils";
|
||||
|
||||
interface UseChatStateProps {
|
||||
search_space_id: string;
|
||||
|
|
@ -22,7 +23,7 @@ export function useChatState({ chat_id }: UseChatStateProps) {
|
|||
const [topK, setTopK] = useState<number>(5);
|
||||
|
||||
useEffect(() => {
|
||||
const bearerToken = localStorage.getItem("surfsense_bearer_token");
|
||||
const bearerToken = getBearerToken();
|
||||
setToken(bearerToken);
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
type SearchSourceConnector,
|
||||
useSearchSourceConnectors,
|
||||
} from "@/hooks/use-search-source-connectors";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
const normalizeListInput = (value: unknown): string[] => {
|
||||
if (Array.isArray(value)) {
|
||||
|
|
@ -178,16 +179,11 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string)
|
|||
setIsFetchingRepos(true);
|
||||
setFetchedRepos(null);
|
||||
try {
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
if (!token) throw new Error("No auth token");
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/github/repositories`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ github_pat: values.github_pat }),
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
// Types for connector API
|
||||
export interface ConnectorConfig {
|
||||
[key: string]: string;
|
||||
|
|
@ -32,14 +34,11 @@ export const getConnectorTypeDisplay = (type: string): string => {
|
|||
export const ConnectorService = {
|
||||
// Create a new connector
|
||||
async createConnector(data: CreateConnectorRequest): Promise<Connector> {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
);
|
||||
|
|
@ -54,13 +53,9 @@ export const ConnectorService = {
|
|||
|
||||
// Get all connectors
|
||||
async getConnectors(skip = 0, limit = 100): Promise<Connector[]> {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors?skip=${skip}&limit=${limit}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -73,13 +68,9 @@ export const ConnectorService = {
|
|||
|
||||
// Get a specific connector
|
||||
async getConnector(connectorId: number): Promise<Connector> {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors/${connectorId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -92,14 +83,11 @@ export const ConnectorService = {
|
|||
|
||||
// Update a connector
|
||||
async updateConnector(connectorId: number, data: CreateConnectorRequest): Promise<Connector> {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors/${connectorId}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
);
|
||||
|
|
@ -114,14 +102,9 @@ export const ConnectorService = {
|
|||
|
||||
// Delete a connector
|
||||
async deleteConnector(connectorId: number): Promise<void> {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors/${connectorId}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
import { useCallback, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
export interface Chunk {
|
||||
id: number;
|
||||
|
|
@ -49,13 +50,10 @@ export function useDocumentByChunk() {
|
|||
setError(null);
|
||||
setDocument(null);
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/by-chunk/${chunkId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "GET",
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
export interface DocumentTypeCount {
|
||||
type: string;
|
||||
|
|
@ -23,11 +24,6 @@ export const useDocumentTypes = (searchSpaceId?: number, lazy: boolean = false)
|
|||
try {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
// Build URL with optional search_space_id query parameter
|
||||
const url = new URL(
|
||||
|
|
@ -37,12 +33,9 @@ export const useDocumentTypes = (searchSpaceId?: number, lazy: boolean = false)
|
|||
url.searchParams.append("search_space_id", spaceId.toString());
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
const response = await authenticatedFetch(url.toString(), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
import { normalizeListResponse } from "@/lib/pagination";
|
||||
|
||||
export interface Document {
|
||||
|
|
@ -78,14 +79,9 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption
|
|||
params.append("document_types", effectiveDocumentTypes.join(","));
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents?${params.toString()}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -159,14 +155,9 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption
|
|||
params.append("document_types", effectiveDocumentTypes.join(","));
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/search?${params.toString()}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -193,14 +184,9 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption
|
|||
const deleteDocument = useCallback(
|
||||
async (documentId: number) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/${documentId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "DELETE",
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -228,14 +214,9 @@ export function useDocuments(searchSpaceId: number, options?: UseDocumentsOption
|
|||
search_space_id: searchSpaceId.toString(),
|
||||
});
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/documents/type-counts?${params.toString()}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
export interface LLMConfig {
|
||||
id: number;
|
||||
|
|
@ -61,14 +62,9 @@ export function useLLMConfigs(searchSpaceId: number | null) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/llm-configs?search_space_id=${searchSpaceId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -92,14 +88,11 @@ export function useLLMConfigs(searchSpaceId: number | null) {
|
|||
|
||||
const createLLMConfig = async (config: CreateLLMConfig): Promise<LLMConfig | null> => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/llm-configs`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(config),
|
||||
}
|
||||
);
|
||||
|
|
@ -122,14 +115,9 @@ export function useLLMConfigs(searchSpaceId: number | null) {
|
|||
|
||||
const deleteLLMConfig = async (id: number): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/llm-configs/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -151,14 +139,11 @@ export function useLLMConfigs(searchSpaceId: number | null) {
|
|||
config: UpdateLLMConfig
|
||||
): Promise<LLMConfig | null> => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/llm-configs/${id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(config),
|
||||
}
|
||||
);
|
||||
|
|
@ -203,14 +188,9 @@ export function useLLMPreferences(searchSpaceId: number | null) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-spaces/${searchSpaceId}/llm-preferences`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -239,14 +219,11 @@ export function useLLMPreferences(searchSpaceId: number | null) {
|
|||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-spaces/${searchSpaceId}/llm-preferences`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(newPreferences),
|
||||
}
|
||||
);
|
||||
|
|
@ -293,14 +270,9 @@ export function useGlobalLLMConfigs() {
|
|||
const fetchGlobalConfigs = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/global-llm-configs`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
export type LogLevel = "DEBUG" | "INFO" | "WARNING" | "ERROR" | "CRITICAL";
|
||||
export type LogStatus = "IN_PROGRESS" | "SUCCESS" | "FAILED";
|
||||
|
|
@ -95,14 +96,9 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) {
|
|||
if (options.skip !== undefined) params.append("skip", options.skip.toString());
|
||||
if (options.limit !== undefined) params.append("limit", options.limit.toString());
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs?${params}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -147,14 +143,14 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) {
|
|||
// Function to create a new log
|
||||
const createLog = useCallback(async (logData: Omit<Log, "id" | "created_at">) => {
|
||||
try {
|
||||
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")}`,
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify(logData),
|
||||
});
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs`,
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "POST",
|
||||
body: JSON.stringify(logData),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
|
|
@ -179,13 +175,10 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) {
|
|||
updateData: Partial<Omit<Log, "id" | "created_at" | "search_space_id">>
|
||||
) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/${logId}`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "PUT",
|
||||
body: JSON.stringify(updateData),
|
||||
}
|
||||
|
|
@ -212,14 +205,9 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) {
|
|||
// Function to delete a log
|
||||
const deleteLog = useCallback(async (logId: number) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/${logId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "DELETE",
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -240,14 +228,9 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) {
|
|||
// Function to get a single log
|
||||
const getLog = useCallback(async (logId: number) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/${logId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -287,14 +270,9 @@ export function useLogsSummary(searchSpaceId: number, hours: number = 24) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/logs/search-space/${searchSpaceId}/summary?hours=${hours}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch, getBearerToken, handleUnauthorized } from "@/lib/auth-utils";
|
||||
|
||||
// ============ Types ============
|
||||
|
||||
|
|
@ -105,22 +106,11 @@ export function useMembers(searchSpaceId: number) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/members`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem("surfsense_bearer_token");
|
||||
window.location.href = "/";
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || "Failed to fetch members");
|
||||
|
|
@ -145,13 +135,10 @@ export function useMembers(searchSpaceId: number) {
|
|||
const updateMemberRole = useCallback(
|
||||
async (membershipId: number, roleId: number | null) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/members/${membershipId}`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ role_id: roleId }),
|
||||
}
|
||||
|
|
@ -177,14 +164,9 @@ export function useMembers(searchSpaceId: number) {
|
|||
const removeMember = useCallback(
|
||||
async (membershipId: number) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/members/${membershipId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "DELETE",
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -205,14 +187,9 @@ export function useMembers(searchSpaceId: number) {
|
|||
|
||||
const leaveSearchSpace = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/members/me`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "DELETE",
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -251,22 +228,11 @@ export function useRoles(searchSpaceId: number) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/roles`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem("surfsense_bearer_token");
|
||||
window.location.href = "/";
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || "Failed to fetch roles");
|
||||
|
|
@ -291,13 +257,10 @@ export function useRoles(searchSpaceId: number) {
|
|||
const createRole = useCallback(
|
||||
async (roleData: RoleCreate) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/roles`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "POST",
|
||||
body: JSON.stringify(roleData),
|
||||
}
|
||||
|
|
@ -323,13 +286,10 @@ export function useRoles(searchSpaceId: number) {
|
|||
const updateRole = useCallback(
|
||||
async (roleId: number, roleData: RoleUpdate) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/roles/${roleId}`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "PUT",
|
||||
body: JSON.stringify(roleData),
|
||||
}
|
||||
|
|
@ -355,14 +315,9 @@ export function useRoles(searchSpaceId: number) {
|
|||
const deleteRole = useCallback(
|
||||
async (roleId: number) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/roles/${roleId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "DELETE",
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -404,22 +359,11 @@ export function useInvites(searchSpaceId: number) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/invites`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem("surfsense_bearer_token");
|
||||
window.location.href = "/";
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || "Failed to fetch invites");
|
||||
|
|
@ -444,13 +388,10 @@ export function useInvites(searchSpaceId: number) {
|
|||
const createInvite = useCallback(
|
||||
async (inviteData: InviteCreate) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/invites`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "POST",
|
||||
body: JSON.stringify(inviteData),
|
||||
}
|
||||
|
|
@ -476,13 +417,10 @@ export function useInvites(searchSpaceId: number) {
|
|||
const updateInvite = useCallback(
|
||||
async (inviteId: number, inviteData: InviteUpdate) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/invites/${inviteId}`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "PUT",
|
||||
body: JSON.stringify(inviteData),
|
||||
}
|
||||
|
|
@ -508,14 +446,9 @@ export function useInvites(searchSpaceId: number) {
|
|||
const revokeInvite = useCallback(
|
||||
async (inviteId: number) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/invites/${inviteId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "DELETE",
|
||||
}
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -555,14 +488,9 @@ export function usePermissions() {
|
|||
const fetchPermissions = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/permissions`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -619,22 +547,11 @@ export function useUserAccess(searchSpaceId: number) {
|
|||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}/my-access`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem("surfsense_bearer_token");
|
||||
window.location.href = "/";
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || "Failed to fetch access info");
|
||||
|
|
@ -737,13 +654,10 @@ export function useInviteInfo(inviteCode: string | null) {
|
|||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/invites/accept`,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: "POST",
|
||||
body: JSON.stringify({ invite_code: inviteCode }),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import { authenticatedFetch, getBearerToken, handleUnauthorized } from "@/lib/auth-utils";
|
||||
|
||||
export interface SearchSourceConnector {
|
||||
id: number;
|
||||
|
|
@ -66,11 +67,6 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
try {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
// Build URL with optional search_space_id query parameter
|
||||
const url = new URL(
|
||||
|
|
@ -80,12 +76,9 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
url.searchParams.append("search_space_id", spaceId.toString());
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
const response = await authenticatedFetch(url.toString(), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -176,24 +169,15 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
spaceId: number
|
||||
) => {
|
||||
try {
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
// Add search_space_id as a query parameter
|
||||
const url = new URL(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors`
|
||||
);
|
||||
url.searchParams.append("search_space_id", spaceId.toString());
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
const response = await authenticatedFetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(connectorData),
|
||||
});
|
||||
|
||||
|
|
@ -222,20 +206,11 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
>
|
||||
) => {
|
||||
try {
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors/${connectorId}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(connectorData),
|
||||
}
|
||||
);
|
||||
|
|
@ -262,20 +237,11 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
*/
|
||||
const deleteConnector = async (connectorId: number) => {
|
||||
try {
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-source-connectors/${connectorId}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -302,12 +268,6 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
endDate?: string
|
||||
) => {
|
||||
try {
|
||||
const token = localStorage.getItem("surfsense_bearer_token");
|
||||
|
||||
if (!token) {
|
||||
throw new Error("No authentication token found");
|
||||
}
|
||||
|
||||
// Build query parameters
|
||||
const params = new URLSearchParams({
|
||||
search_space_id: searchSpaceId.toString(),
|
||||
|
|
@ -319,16 +279,13 @@ export const useSearchSourceConnectors = (lazy: boolean = false, searchSpaceId?:
|
|||
params.append("end_date", endDate);
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${
|
||||
process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL
|
||||
}/api/v1/search-source-connectors/${connectorId}/index?${params.toString()}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
interface SearchSpace {
|
||||
created_at: string;
|
||||
|
|
@ -29,23 +30,11 @@ export function useSearchSpace({ searchSpaceId, autoFetch = true }: UseSearchSpa
|
|||
if (typeof window === "undefined") return;
|
||||
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (response.status === 401) {
|
||||
// Clear token and redirect to home
|
||||
localStorage.removeItem("surfsense_bearer_token");
|
||||
window.location.href = "/";
|
||||
throw new Error("Unauthorized: Redirecting to login page");
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch search space: ${response.status}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
interface SearchSpace {
|
||||
id: number;
|
||||
|
|
@ -23,19 +24,14 @@ export function useSearchSpaces() {
|
|||
const fetchSearchSpaces = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
toast.error("Not authenticated");
|
||||
throw new Error("Not authenticated");
|
||||
toast.error("Failed to fetch search spaces");
|
||||
throw new Error("Failed to fetch search spaces");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
|
@ -56,19 +52,14 @@ export function useSearchSpaces() {
|
|||
const refreshSearchSpaces = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch(
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
}
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
toast.error("Not authenticated");
|
||||
throw new Error("Not authenticated");
|
||||
toast.error("Failed to fetch search spaces");
|
||||
throw new Error("Failed to fetch search spaces");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
|
|
@ -25,19 +26,10 @@ export function useUser() {
|
|||
if (typeof window === "undefined") return;
|
||||
|
||||
setLoading(true);
|
||||
const response = await fetch(`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/users/me`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`,
|
||||
},
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
// Clear token and redirect to home
|
||||
localStorage.removeItem("surfsense_bearer_token");
|
||||
window.location.href = "/";
|
||||
throw new Error("Unauthorized: Redirecting to login page");
|
||||
}
|
||||
const response = await authenticatedFetch(
|
||||
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/users/me`,
|
||||
{ method: "GET" }
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch user: ${response.status}`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue