From 630880bf7ab0748a27f0df414647ee2eea377718 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Fri, 19 Jun 2026 20:27:17 +0530 Subject: [PATCH] feat: add API access toggle to search space settings --- .../search-space-mutation.atoms.ts | 23 ++++++++++ .../settings/general-settings-manager.tsx | 45 ++++++++++++++++++- .../contracts/types/search-space.types.ts | 14 ++++++ .../lib/apis/search-spaces-api.service.ts | 21 +++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/surfsense_web/atoms/search-spaces/search-space-mutation.atoms.ts b/surfsense_web/atoms/search-spaces/search-space-mutation.atoms.ts index 62f23507b..03d77e00c 100644 --- a/surfsense_web/atoms/search-spaces/search-space-mutation.atoms.ts +++ b/surfsense_web/atoms/search-spaces/search-space-mutation.atoms.ts @@ -3,6 +3,7 @@ import { toast } from "sonner"; import type { CreateSearchSpaceRequest, DeleteSearchSpaceRequest, + UpdateSearchSpaceApiAccessRequest, UpdateSearchSpaceRequest, } from "@/contracts/types/search-space.types"; import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service"; @@ -50,6 +51,28 @@ export const updateSearchSpaceMutationAtom = atomWithMutation((get) => { }; }); +export const updateSearchSpaceApiAccessMutationAtom = atomWithMutation((get) => { + const activeSearchSpaceId = get(activeSearchSpaceIdAtom); + + return { + mutationKey: ["update-search-space-api-access", activeSearchSpaceId], + enabled: !!activeSearchSpaceId, + mutationFn: async (request: UpdateSearchSpaceApiAccessRequest) => { + return searchSpacesApiService.updateSearchSpaceApiAccess(request); + }, + + onSuccess: (_, request: UpdateSearchSpaceApiAccessRequest) => { + toast.success("API access updated successfully"); + queryClient.invalidateQueries({ + queryKey: cacheKeys.searchSpaces.all, + }); + queryClient.invalidateQueries({ + queryKey: cacheKeys.searchSpaces.detail(String(request.id)), + }); + }, + }; +}); + export const deleteSearchSpaceMutationAtom = atomWithMutation((get) => { const activeSearchSpaceId = get(activeSearchSpaceIdAtom); diff --git a/surfsense_web/components/settings/general-settings-manager.tsx b/surfsense_web/components/settings/general-settings-manager.tsx index 68ff21f07..cfbcedbbf 100644 --- a/surfsense_web/components/settings/general-settings-manager.tsx +++ b/surfsense_web/components/settings/general-settings-manager.tsx @@ -5,11 +5,15 @@ import { useAtomValue } from "jotai"; import { useTranslations } from "next-intl"; import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; -import { updateSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms"; +import { + updateSearchSpaceApiAccessMutationAtom, + updateSearchSpaceMutationAtom, +} from "@/atoms/search-spaces/search-space-mutation.atoms"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Skeleton } from "@/components/ui/skeleton"; +import { Switch } from "@/components/ui/switch"; import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service"; import { authenticatedFetch } from "@/lib/auth-utils"; import { buildBackendUrl } from "@/lib/env-config"; @@ -35,10 +39,14 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager }); const { mutateAsync: updateSearchSpace } = useAtomValue(updateSearchSpaceMutationAtom); + const { mutateAsync: updateSearchSpaceApiAccess } = useAtomValue( + updateSearchSpaceApiAccessMutationAtom + ); const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [saving, setSaving] = useState(false); + const [savingApiAccess, setSavingApiAccess] = useState(false); const [isExporting, setIsExporting] = useState(false); const hasSearchSpace = !!searchSpace; const searchSpaceName = searchSpace?.name; @@ -113,6 +121,25 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager handleSave(); }; + const handleApiAccessToggle = useCallback( + async (enabled: boolean) => { + try { + setSavingApiAccess(true); + await updateSearchSpaceApiAccess({ + id: searchSpaceId, + api_access_enabled: enabled, + }); + await fetchSearchSpace(); + } catch (error) { + console.error("Error updating API access:", error); + toast.error(error instanceof Error ? error.message : "Failed to update API access"); + } finally { + setSavingApiAccess(false); + } + }, + [fetchSearchSpace, searchSpaceId, updateSearchSpaceApiAccess] + ); + if (loading) { return (
+ Allow personal access tokens to use this search space. Web and desktop sessions are + not affected. +
+