From 838d1d7f81d391d843fc13e5d09385bdfb8771fd Mon Sep 17 00:00:00 2001 From: Kirill Chernakov Date: Wed, 20 Nov 2024 12:22:15 +0400 Subject: [PATCH] refactor: useHydratedSession instead of built-in useSession (#2407) --- keep-ui/app/ai/ai.tsx | 2 +- keep-ui/app/alerts/ViewAlertModal.tsx | 2 +- .../app/alerts/alert-assign-ticket-modal.tsx | 2 +- .../alerts/alert-associate-incident-modal.tsx | 2 +- .../app/alerts/alert-change-status-modal.tsx | 2 +- .../alerts/alert-create-incident-ai-modal.tsx | 2 +- keep-ui/app/alerts/alert-dismiss-modal.tsx | 2 +- keep-ui/app/alerts/alert-menu.tsx | 2 +- keep-ui/app/alerts/alert-note-modal.tsx | 2 +- keep-ui/app/alerts/alert-presets.tsx | 2 +- .../alert-push-alert-to-server-modal.tsx | 2 +- .../app/alerts/alert-run-workflow-modal.tsx | 2 +- keep-ui/app/alerts/alert-tab-modal.tsx | 6 +- keep-ui/app/alerts/alert-tabs.tsx | 2 +- keep-ui/app/alerts/alerts.tsx | 4 +- keep-ui/app/auth-provider.tsx | 17 ++++- keep-ui/app/dashboard/[id]/dashboard.tsx | 65 +++++++++++++------ .../deduplication/DeduplicationSidebar.tsx | 2 +- .../app/deduplication/DeduplicationTable.tsx | 2 +- .../create-or-update-extraction-rule.tsx | 2 +- keep-ui/app/extraction/extractions-table.tsx | 2 +- keep-ui/app/frigade-provider.tsx | 4 +- .../[id]/activity/incident-activity.tsx | 2 +- .../activity/ui/IncidentActivityComment.tsx | 2 +- .../[id]/alerts/incident-alert-menu.tsx | 2 +- keep-ui/app/layout.tsx | 10 ++- .../create-or-update-maintenance-rule.tsx | 2 +- .../maintenance/maintenance-rules-table.tsx | 2 +- .../app/mapping/create-or-edit-mapping.tsx | 2 +- keep-ui/app/mapping/rules-table.tsx | 2 +- keep-ui/app/providers/page.client.tsx | 2 +- keep-ui/app/providers/provider-form.tsx | 2 +- .../CorrelationSidebarBody.tsx | 2 +- .../rules/CorrelationSidebar/DeleteRule.tsx | 2 +- keep-ui/app/settings/auth/permissions-tab.tsx | 2 +- keep-ui/app/settings/auth/users-sidebar.tsx | 12 ++-- keep-ui/app/settings/settings.client.tsx | 30 ++++----- keep-ui/app/topology/model/useTopology.ts | 2 +- .../topology/model/useTopologyApplications.ts | 2 +- .../workflows/[workflow_id]/executions.tsx | 2 +- keep-ui/app/workflows/builder/page.client.tsx | 2 +- .../builder/workflow-execution-results.tsx | 6 +- keep-ui/app/workflows/dragndrop.tsx | 2 +- .../workflows/manual-run-workflow-modal.tsx | 2 +- keep-ui/app/workflows/workflow-tile.tsx | 2 +- keep-ui/app/workflows/workflows.client.tsx | 2 +- .../incidents/model/useIncidentActions.tsx | 2 +- .../shared/lib/hooks/useHydratedSession.tsx | 31 +++++++++ keep-ui/shared/ui/PostHogPageView.tsx | 2 +- keep-ui/utils/hooks/useAI.ts | 2 +- keep-ui/utils/hooks/useAlertQuality.ts | 6 +- keep-ui/utils/hooks/useAlerts.ts | 2 +- .../utils/hooks/useDashboardMetricWidgets.ts | 47 +++++++------- keep-ui/utils/hooks/useDashboardPresets.ts | 45 ++++++++----- keep-ui/utils/hooks/useDashboards.ts | 2 +- keep-ui/utils/hooks/useDeduplicationRules.ts | 2 +- keep-ui/utils/hooks/useExtractionRules.ts | 2 +- keep-ui/utils/hooks/useGroups.ts | 2 +- keep-ui/utils/hooks/useIncidents.ts | 2 +- keep-ui/utils/hooks/useMaintenanceRules.ts | 2 +- keep-ui/utils/hooks/useMappingRules.ts | 2 +- keep-ui/utils/hooks/usePermissions.ts | 2 +- keep-ui/utils/hooks/usePresets.ts | 2 +- keep-ui/utils/hooks/useProviders.ts | 2 +- keep-ui/utils/hooks/usePusher.ts | 2 +- keep-ui/utils/hooks/useRoles.ts | 2 +- keep-ui/utils/hooks/useRules.ts | 2 +- keep-ui/utils/hooks/useScopes.ts | 2 +- keep-ui/utils/hooks/useSearchAlerts.ts | 2 +- keep-ui/utils/hooks/useTags.ts | 2 +- keep-ui/utils/hooks/useUsers.ts | 2 +- keep-ui/utils/hooks/useWorkflowExecutions.ts | 2 +- keep-ui/utils/hooks/useWorkflowRun.ts | 2 +- keep-ui/utils/hooks/useWorkflows.ts | 2 +- 74 files changed, 245 insertions(+), 160 deletions(-) create mode 100644 keep-ui/shared/lib/hooks/useHydratedSession.tsx diff --git a/keep-ui/app/ai/ai.tsx b/keep-ui/app/ai/ai.tsx index 7e9d23aa7..2446337a7 100644 --- a/keep-ui/app/ai/ai.tsx +++ b/keep-ui/app/ai/ai.tsx @@ -1,7 +1,7 @@ "use client"; import { Card, List, ListItem, Title, Subtitle } from "@tremor/react"; import { useAIStats, usePollAILogs } from "utils/hooks/useAI"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { toast } from "react-toastify"; import { useEffect, useState, useRef, FormEvent } from "react"; diff --git a/keep-ui/app/alerts/ViewAlertModal.tsx b/keep-ui/app/alerts/ViewAlertModal.tsx index 6bbeca28f..7bc404172 100644 --- a/keep-ui/app/alerts/ViewAlertModal.tsx +++ b/keep-ui/app/alerts/ViewAlertModal.tsx @@ -3,7 +3,7 @@ import Modal from "@/components/ui/Modal"; // Ensure this path matches your proj import { Button, Icon, Switch, Text } from "@tremor/react"; import { toast } from "react-toastify"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { XMarkIcon } from "@heroicons/react/24/outline"; import "./ViewAlertModal.css"; import React, { useState } from "react"; diff --git a/keep-ui/app/alerts/alert-assign-ticket-modal.tsx b/keep-ui/app/alerts/alert-assign-ticket-modal.tsx index f3920c764..0ca7bae0a 100644 --- a/keep-ui/app/alerts/alert-assign-ticket-modal.tsx +++ b/keep-ui/app/alerts/alert-assign-ticket-modal.tsx @@ -4,7 +4,7 @@ import { Button, TextInput, Text } from "@tremor/react"; import { PlusIcon } from "@heroicons/react/20/solid"; import { useForm, Controller, SubmitHandler } from "react-hook-form"; import { Providers } from "./../providers/providers"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { AlertDto } from "./models"; import Modal from "@/components/ui/Modal"; diff --git a/keep-ui/app/alerts/alert-associate-incident-modal.tsx b/keep-ui/app/alerts/alert-associate-incident-modal.tsx index 9d59afdbf..923d30cd8 100644 --- a/keep-ui/app/alerts/alert-associate-incident-modal.tsx +++ b/keep-ui/app/alerts/alert-associate-incident-modal.tsx @@ -2,7 +2,7 @@ import Modal from "@/components/ui/Modal"; import { Button, Divider, Title } from "@tremor/react"; import Select from "@/components/ui/Select"; import { CreateOrUpdateIncidentForm } from "@/features/create-or-update-incident"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { FormEvent, useCallback, useEffect, useState } from "react"; import { toast } from "react-toastify"; import { useApiUrl } from "utils/hooks/useConfig"; diff --git a/keep-ui/app/alerts/alert-change-status-modal.tsx b/keep-ui/app/alerts/alert-change-status-modal.tsx index d090599dc..f68f46e61 100644 --- a/keep-ui/app/alerts/alert-change-status-modal.tsx +++ b/keep-ui/app/alerts/alert-change-status-modal.tsx @@ -9,7 +9,7 @@ import Select, { import { useState } from "react"; import { AlertDto, Status } from "./models"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { toast } from "react-toastify"; import { CheckCircleIcon, diff --git a/keep-ui/app/alerts/alert-create-incident-ai-modal.tsx b/keep-ui/app/alerts/alert-create-incident-ai-modal.tsx index ada499e65..9d077ed66 100644 --- a/keep-ui/app/alerts/alert-create-incident-ai-modal.tsx +++ b/keep-ui/app/alerts/alert-create-incident-ai-modal.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; import Modal from "@/components/ui/Modal"; import { Callout, Button, Title, Card } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { toast } from "react-toastify"; import Loading from "../loading"; import { AlertDto } from "./models"; diff --git a/keep-ui/app/alerts/alert-dismiss-modal.tsx b/keep-ui/app/alerts/alert-dismiss-modal.tsx index 11bf3d63f..93976f22d 100644 --- a/keep-ui/app/alerts/alert-dismiss-modal.tsx +++ b/keep-ui/app/alerts/alert-dismiss-modal.tsx @@ -17,7 +17,7 @@ import "react-quill/dist/quill.snow.css"; import { AlertDto } from "./models"; import { format, set, isSameDay, isAfter, addMinutes } from "date-fns"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { usePresets } from "utils/hooks/usePresets"; import { useAlerts } from "utils/hooks/useAlerts"; import { toast } from "react-toastify"; diff --git a/keep-ui/app/alerts/alert-menu.tsx b/keep-ui/app/alerts/alert-menu.tsx index 997be6959..4784090d2 100644 --- a/keep-ui/app/alerts/alert-menu.tsx +++ b/keep-ui/app/alerts/alert-menu.tsx @@ -12,7 +12,7 @@ import { } from "@heroicons/react/24/outline"; import { IoNotificationsOffOutline } from "react-icons/io5"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import Link from "next/link"; import { ProviderMethod } from "app/providers/providers"; diff --git a/keep-ui/app/alerts/alert-note-modal.tsx b/keep-ui/app/alerts/alert-note-modal.tsx index a737059a9..fb9f6910b 100644 --- a/keep-ui/app/alerts/alert-note-modal.tsx +++ b/keep-ui/app/alerts/alert-note-modal.tsx @@ -7,7 +7,7 @@ const ReactQuill = import "react-quill/dist/quill.snow.css"; import { Button } from "@tremor/react"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { AlertDto } from "./models"; import Modal from "@/components/ui/Modal"; diff --git a/keep-ui/app/alerts/alert-presets.tsx b/keep-ui/app/alerts/alert-presets.tsx index 5263b7b1f..217ff5fc2 100644 --- a/keep-ui/app/alerts/alert-presets.tsx +++ b/keep-ui/app/alerts/alert-presets.tsx @@ -4,7 +4,7 @@ import Modal from "@/components/ui/Modal"; import { Button, Subtitle, TextInput, Switch, Text } from "@tremor/react"; import { useApiUrl } from "utils/hooks/useConfig"; import { toast } from "react-toastify"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { usePresets } from "utils/hooks/usePresets"; import { useTags } from "utils/hooks/useTags"; import { useRouter } from "next/navigation"; diff --git a/keep-ui/app/alerts/alert-push-alert-to-server-modal.tsx b/keep-ui/app/alerts/alert-push-alert-to-server-modal.tsx index 76931c8ed..44576e546 100644 --- a/keep-ui/app/alerts/alert-push-alert-to-server-modal.tsx +++ b/keep-ui/app/alerts/alert-push-alert-to-server-modal.tsx @@ -7,7 +7,7 @@ import { FieldValues, } from "react-hook-form"; import Modal from "@/components/ui/Modal"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { useProviders } from "utils/hooks/useProviders"; import ImageWithFallback from "@/components/ImageWithFallback"; diff --git a/keep-ui/app/alerts/alert-run-workflow-modal.tsx b/keep-ui/app/alerts/alert-run-workflow-modal.tsx index 3ade1e15a..514719fb4 100644 --- a/keep-ui/app/alerts/alert-run-workflow-modal.tsx +++ b/keep-ui/app/alerts/alert-run-workflow-modal.tsx @@ -3,7 +3,7 @@ import { AlertDto } from "./models"; import Modal from "@/components/ui/Modal"; import { useWorkflows } from "utils/hooks/useWorkflows"; import { useState } from "react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { toast } from "react-toastify"; import { useRouter } from "next/navigation"; diff --git a/keep-ui/app/alerts/alert-tab-modal.tsx b/keep-ui/app/alerts/alert-tab-modal.tsx index d5a99e7d6..c8a2b232d 100644 --- a/keep-ui/app/alerts/alert-tab-modal.tsx +++ b/keep-ui/app/alerts/alert-tab-modal.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import Modal from "@/components/ui/Modal"; import { Button, TextInput } from "@tremor/react"; import { AlertsRulesBuilder } from "app/alerts/alerts-rules-builder"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; interface AlertTabModalProps { @@ -114,8 +114,8 @@ const AlertTabModal = ({ !newTabName ? "Tab name is required" : !newTabFilter - ? "Tab filter is required (notice you need to click 'enter' to apply the filter)" - : "" + ? "Tab filter is required (notice you need to click 'enter' to apply the filter)" + : "" } > Add Tab diff --git a/keep-ui/app/alerts/alert-tabs.tsx b/keep-ui/app/alerts/alert-tabs.tsx index 42c8ea938..2413c4076 100644 --- a/keep-ui/app/alerts/alert-tabs.tsx +++ b/keep-ui/app/alerts/alert-tabs.tsx @@ -5,7 +5,7 @@ import AlertTabModal from "./alert-tab-modal"; import { evalWithContext } from "./alerts-rules-builder"; import { XMarkIcon } from "@heroicons/react/24/outline"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; interface Tab { id?: string; name: string; diff --git a/keep-ui/app/alerts/alerts.tsx b/keep-ui/app/alerts/alerts.tsx index 3aa011e64..4d0fe7117 100644 --- a/keep-ui/app/alerts/alerts.tsx +++ b/keep-ui/app/alerts/alerts.tsx @@ -18,8 +18,7 @@ import { useRouter, useSearchParams } from "next/navigation"; import AlertChangeStatusModal from "./alert-change-status-modal"; import { useAlertPolling } from "utils/hooks/usePusher"; import NotFound from "@/app/not-found"; -import { useMounted } from "@/shared/lib/hooks/useMounted"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; const defaultPresets: Preset[] = [ { @@ -111,7 +110,6 @@ export default function Alerts({ presetName }: AlertsProps) { error: alertsError, } = usePresetAlerts(selectedPreset ? selectedPreset.name : ""); - // const isMounted = useMounted(); const { status: sessionStatus } = useSession(); const isLoading = isAsyncLoading || sessionStatus === "loading"; diff --git a/keep-ui/app/auth-provider.tsx b/keep-ui/app/auth-provider.tsx index 21e157dfc..8a3107208 100644 --- a/keep-ui/app/auth-provider.tsx +++ b/keep-ui/app/auth-provider.tsx @@ -1,11 +1,24 @@ "use client"; +import { Session } from "next-auth"; import { SessionProvider } from "next-auth/react"; +declare global { + interface Window { + __NEXT_AUTH_SESSION__?: Session | null; + } +} + type Props = { children?: React.ReactNode; + session?: Session | null; }; -export const NextAuthProvider = ({ children }: Props) => { - return {children} +export const NextAuthProvider = ({ children, session }: Props) => { + // Hydrate session on mount + if (typeof window !== "undefined" && !!session) { + window.__NEXT_AUTH_SESSION__ = session; + } + + return {children}; }; diff --git a/keep-ui/app/dashboard/[id]/dashboard.tsx b/keep-ui/app/dashboard/[id]/dashboard.tsx index 77b060624..965f7f5fa 100644 --- a/keep-ui/app/dashboard/[id]/dashboard.tsx +++ b/keep-ui/app/dashboard/[id]/dashboard.tsx @@ -1,20 +1,29 @@ "use client"; -import {useParams} from "next/navigation"; -import {ChangeEvent, useEffect, useState} from "react"; +import { useParams } from "next/navigation"; +import { ChangeEvent, useEffect, useState } from "react"; import GridLayout from "../GridLayout"; import WidgetModal from "../WidgetModal"; -import {Button, Card, Icon, Subtitle, TextInput} from "@tremor/react"; -import {GenericsMetrics, LayoutItem, Threshold, WidgetData, WidgetType} from "../types"; -import {Preset} from "app/alerts/models"; -import {FiEdit2, FiSave} from "react-icons/fi"; -import {useSession} from "next-auth/react"; -import {useDashboards} from "utils/hooks/useDashboards"; -import {useApiUrl} from "utils/hooks/useConfig"; +import { Button, Card, Icon, Subtitle, TextInput } from "@tremor/react"; +import { + GenericsMetrics, + LayoutItem, + Threshold, + WidgetData, + WidgetType, +} from "../types"; +import { Preset } from "app/alerts/models"; +import { FiEdit2, FiSave } from "react-icons/fi"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; +import { useDashboards } from "utils/hooks/useDashboards"; +import { useApiUrl } from "utils/hooks/useConfig"; import "./../styles.css"; -import {toast} from "react-toastify"; -import {GenericFilters} from "@/components/filters/GenericFilters"; -import {useDashboardPreset} from "utils/hooks/useDashboardPresets"; -import {MetricsWidget, useDashboardMetricWidgets} from '@/utils/hooks/useDashboardMetricWidgets'; +import { toast } from "react-toastify"; +import { GenericFilters } from "@/components/filters/GenericFilters"; +import { useDashboardPreset } from "utils/hooks/useDashboardPresets"; +import { + MetricsWidget, + useDashboardMetricWidgets, +} from "@/utils/hooks/useDashboardMetricWidgets"; const DASHBOARD_FILTERS = [ { @@ -33,7 +42,7 @@ const DashboardPage = () => { const [isModalOpen, setIsModalOpen] = useState(false); const [layout, setLayout] = useState([]); const [widgetData, setWidgetData] = useState([]); - const {widgets: allMetricWidgets} = useDashboardMetricWidgets(true); + const { widgets: allMetricWidgets } = useDashboardMetricWidgets(true); const [editingItem, setEditingItem] = useState(null); const [dashboardName, setDashboardName] = useState(decodeURIComponent(id)); const [isEditingName, setIsEditingName] = useState(false); @@ -59,7 +68,9 @@ const DashboardPage = () => { const closeModal = () => setIsModalOpen(false); const handleAddWidget = ( - name: string, widgetType: WidgetType, preset?: Preset , + name: string, + widgetType: WidgetType, + preset?: Preset, thresholds?: Threshold[], metric?: MetricsWidget, genericMetrics?: GenericsMetrics @@ -69,10 +80,25 @@ const DashboardPage = () => { i: uniqueId, x: (layout.length % 12) * 2, y: Math.floor(layout.length / 12) * 2, - w: widgetType === WidgetType.GENERICS_METRICS ? 12 : widgetType === WidgetType.METRIC ? 6 : 3, - h: widgetType === WidgetType.GENERICS_METRICS ? 20 : widgetType === WidgetType.METRIC ? 8 : 3, + w: + widgetType === WidgetType.GENERICS_METRICS + ? 12 + : widgetType === WidgetType.METRIC + ? 6 + : 3, + h: + widgetType === WidgetType.GENERICS_METRICS + ? 20 + : widgetType === WidgetType.METRIC + ? 8 + : 3, minW: widgetType === WidgetType.GENERICS_METRICS ? 10 : 2, - minH: widgetType === WidgetType.GENERICS_METRICS ? 15 : widgetType === WidgetType.METRIC ? 7 : 3, + minH: + widgetType === WidgetType.GENERICS_METRICS + ? 15 + : widgetType === WidgetType.METRIC + ? 7 + : 3, static: false, }; const newWidget: WidgetData = { @@ -82,7 +108,7 @@ const DashboardPage = () => { name, widgetType, genericMetrics, - metric + metric, }; setLayout((prevLayout) => [...prevLayout, newItem]); setWidgetData((prevData) => [...prevData, newWidget]); @@ -90,7 +116,6 @@ const DashboardPage = () => { const handleEditWidget = (id: string, update?: WidgetData) => { let itemToEdit = widgetData.find((d) => d.i === id) || null; - console.log(itemToEdit, update) if (itemToEdit && update) { setEditingItem({ ...itemToEdit, ...update }); } else { diff --git a/keep-ui/app/deduplication/DeduplicationSidebar.tsx b/keep-ui/app/deduplication/DeduplicationSidebar.tsx index 0a3bf8943..48a6d808e 100644 --- a/keep-ui/app/deduplication/DeduplicationSidebar.tsx +++ b/keep-ui/app/deduplication/DeduplicationSidebar.tsx @@ -24,7 +24,7 @@ import { InformationCircleIcon, } from "@heroicons/react/24/outline"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { KeyedMutator } from "swr"; interface ProviderOption { diff --git a/keep-ui/app/deduplication/DeduplicationTable.tsx b/keep-ui/app/deduplication/DeduplicationTable.tsx index 05d634451..3951fbaaa 100644 --- a/keep-ui/app/deduplication/DeduplicationTable.tsx +++ b/keep-ui/app/deduplication/DeduplicationTable.tsx @@ -25,7 +25,7 @@ import DeduplicationSidebar from "app/deduplication/DeduplicationSidebar"; import { TrashIcon, PauseIcon, PlusIcon } from "@heroicons/react/24/outline"; import Image from "next/image"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; const columnHelper = createColumnHelper(); diff --git a/keep-ui/app/extraction/create-or-update-extraction-rule.tsx b/keep-ui/app/extraction/create-or-update-extraction-rule.tsx index a770f68c9..11d7c032b 100644 --- a/keep-ui/app/extraction/create-or-update-extraction-rule.tsx +++ b/keep-ui/app/extraction/create-or-update-extraction-rule.tsx @@ -13,7 +13,7 @@ import { Switch, Badge, } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { FormEvent, useEffect, useState } from "react"; import { toast } from "react-toastify"; import { useApiUrl } from "utils/hooks/useConfig"; diff --git a/keep-ui/app/extraction/extractions-table.tsx b/keep-ui/app/extraction/extractions-table.tsx index 48fcb7f51..7b621b05b 100644 --- a/keep-ui/app/extraction/extractions-table.tsx +++ b/keep-ui/app/extraction/extractions-table.tsx @@ -18,7 +18,7 @@ import { useReactTable, } from "@tanstack/react-table"; import { MdRemoveCircle, MdModeEdit } from "react-icons/md"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { useMappings } from "utils/hooks/useMappingRules"; import { toast } from "react-toastify"; diff --git a/keep-ui/app/frigade-provider.tsx b/keep-ui/app/frigade-provider.tsx index 3d98f4aa3..2ae5b4619 100644 --- a/keep-ui/app/frigade-provider.tsx +++ b/keep-ui/app/frigade-provider.tsx @@ -1,7 +1,7 @@ "use client"; import * as Frigade from "@frigade/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; export const FrigadeProvider = ({ children, }: { @@ -14,7 +14,7 @@ export const FrigadeProvider = ({ userId={ session?.user.email === "keep" ? undefined - : session?.user.email ?? session?.user.name + : (session?.user.email ?? session?.user.name) } theme={{ colors: { diff --git a/keep-ui/app/incidents/[id]/activity/incident-activity.tsx b/keep-ui/app/incidents/[id]/activity/incident-activity.tsx index 3b6ea0787..7a62633f6 100644 --- a/keep-ui/app/incidents/[id]/activity/incident-activity.tsx +++ b/keep-ui/app/incidents/[id]/activity/incident-activity.tsx @@ -11,7 +11,7 @@ import { usePollIncidentComments, } from "@/utils/hooks/useIncidents"; import { useAlerts } from "@/utils/hooks/useAlerts"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { IncidentActivityItem } from "./ui/IncidentActivityItem"; import { IncidentActivityComment } from "./ui/IncidentActivityComment"; import { useMemo } from "react"; diff --git a/keep-ui/app/incidents/[id]/activity/ui/IncidentActivityComment.tsx b/keep-ui/app/incidents/[id]/activity/ui/IncidentActivityComment.tsx index 2cd8f0b77..d015b02e9 100644 --- a/keep-ui/app/incidents/[id]/activity/ui/IncidentActivityComment.tsx +++ b/keep-ui/app/incidents/[id]/activity/ui/IncidentActivityComment.tsx @@ -2,7 +2,7 @@ import { IncidentDto } from "@/entities/incidents/model"; import { AuditEvent } from "@/utils/hooks/useAlerts"; import { useApiUrl } from "@/utils/hooks/useConfig"; import { TextInput, Button } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useState, useCallback, useEffect } from "react"; import { toast } from "react-toastify"; import { KeyedMutator } from "swr"; diff --git a/keep-ui/app/incidents/[id]/alerts/incident-alert-menu.tsx b/keep-ui/app/incidents/[id]/alerts/incident-alert-menu.tsx index 03d7c615e..f902df664 100644 --- a/keep-ui/app/incidents/[id]/alerts/incident-alert-menu.tsx +++ b/keep-ui/app/incidents/[id]/alerts/incident-alert-menu.tsx @@ -1,6 +1,6 @@ import { Icon } from "@tremor/react"; import { AlertDto } from "app/alerts/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { toast } from "react-toastify"; import { useApiUrl } from "utils/hooks/useConfig"; import { useIncidentAlerts } from "utils/hooks/useIncidents"; diff --git a/keep-ui/app/layout.tsx b/keep-ui/app/layout.tsx index d7b0f90ab..a8ee5503a 100644 --- a/keep-ui/app/layout.tsx +++ b/keep-ui/app/layout.tsx @@ -7,11 +7,13 @@ import { TopologyPollingContextProvider } from "@/app/topology/model/TopologyPol import { FrigadeProvider } from "./frigade-provider"; import { getConfig } from "@/shared/lib/server/getConfig"; import { ConfigProvider } from "./config-provider"; -import "./globals.css"; -import "react-toastify/dist/ReactToastify.css"; import { PHProvider } from "./posthog-provider"; import dynamic from "next/dynamic"; import ReadOnlyBanner from "./read-only-banner"; +import { getServerSession } from "next-auth"; +import { authOptions } from "@/pages/api/auth/[...nextauth]"; +import "./globals.css"; +import "react-toastify/dist/ReactToastify.css"; const PostHogPageView = dynamic(() => import("@/shared/ui/PostHogPageView"), { ssr: false, @@ -29,12 +31,14 @@ type RootLayoutProps = { export default async function RootLayout({ children }: RootLayoutProps) { const config = getConfig(); + const session = await getServerSession(authOptions); + return ( - + {/* @ts-ignore-error Server Component */} diff --git a/keep-ui/app/maintenance/create-or-update-maintenance-rule.tsx b/keep-ui/app/maintenance/create-or-update-maintenance-rule.tsx index fc50ca66d..9a71bc59f 100644 --- a/keep-ui/app/maintenance/create-or-update-maintenance-rule.tsx +++ b/keep-ui/app/maintenance/create-or-update-maintenance-rule.tsx @@ -10,7 +10,7 @@ import { Select, SelectItem, } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { FormEvent, useEffect, useState } from "react"; import { toast } from "react-toastify"; import { useApiUrl } from "utils/hooks/useConfig"; diff --git a/keep-ui/app/maintenance/maintenance-rules-table.tsx b/keep-ui/app/maintenance/maintenance-rules-table.tsx index 819caa4c6..790082e83 100644 --- a/keep-ui/app/maintenance/maintenance-rules-table.tsx +++ b/keep-ui/app/maintenance/maintenance-rules-table.tsx @@ -17,7 +17,7 @@ import { useReactTable, } from "@tanstack/react-table"; import { MdRemoveCircle, MdModeEdit } from "react-icons/md"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { toast } from "react-toastify"; import { useApiUrl } from "utils/hooks/useConfig"; import { MaintenanceRule } from "./model"; diff --git a/keep-ui/app/mapping/create-or-edit-mapping.tsx b/keep-ui/app/mapping/create-or-edit-mapping.tsx index 0145999fa..5c0b61a95 100644 --- a/keep-ui/app/mapping/create-or-edit-mapping.tsx +++ b/keep-ui/app/mapping/create-or-edit-mapping.tsx @@ -17,7 +17,7 @@ import { TabPanels, TabPanel, } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { ChangeEvent, FormEvent, diff --git a/keep-ui/app/mapping/rules-table.tsx b/keep-ui/app/mapping/rules-table.tsx index 476ec90f3..dc80a5326 100644 --- a/keep-ui/app/mapping/rules-table.tsx +++ b/keep-ui/app/mapping/rules-table.tsx @@ -18,7 +18,7 @@ import { ExpandedState, } from "@tanstack/react-table"; import { MdRemoveCircle, MdModeEdit } from "react-icons/md"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { useMappings } from "utils/hooks/useMappingRules"; import { toast } from "react-toastify"; diff --git a/keep-ui/app/providers/page.client.tsx b/keep-ui/app/providers/page.client.tsx index b44cdf109..aac212780 100644 --- a/keep-ui/app/providers/page.client.tsx +++ b/keep-ui/app/providers/page.client.tsx @@ -1,6 +1,6 @@ "use client"; import { defaultProvider, Provider } from "./providers"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { KeepApiError } from "@/shared/lib/KeepApiError"; import { useApiUrl } from "utils/hooks/useConfig"; import ProvidersTiles from "./providers-tiles"; diff --git a/keep-ui/app/providers/provider-form.tsx b/keep-ui/app/providers/provider-form.tsx index 80e519a7d..5d59cf35a 100644 --- a/keep-ui/app/providers/provider-form.tsx +++ b/keep-ui/app/providers/provider-form.tsx @@ -2,7 +2,7 @@ // There's also a lot of s**t in here, but it works for now 🤷‍♂️ // @ts-nocheck import React, { useEffect, useState, useRef, useCallback } from "react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { Provider } from "./providers"; import { useApiUrl } from "utils/hooks/useConfig"; import Image from "next/image"; diff --git a/keep-ui/app/rules/CorrelationSidebar/CorrelationSidebarBody.tsx b/keep-ui/app/rules/CorrelationSidebar/CorrelationSidebarBody.tsx index ffb225c04..29d5d8fa2 100644 --- a/keep-ui/app/rules/CorrelationSidebar/CorrelationSidebarBody.tsx +++ b/keep-ui/app/rules/CorrelationSidebar/CorrelationSidebarBody.tsx @@ -7,7 +7,7 @@ import { FormProvider, SubmitHandler, useForm } from "react-hook-form"; import { CorrelationForm } from "./CorrelationForm"; import { CorrelationGroups } from "./CorrelationGroups"; import { CorrelationSubmission } from "./CorrelationSubmission"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useRules } from "utils/hooks/useRules"; import { CorrelationForm as CorrelationFormType } from "."; import { useRouter, useSearchParams } from "next/navigation"; diff --git a/keep-ui/app/rules/CorrelationSidebar/DeleteRule.tsx b/keep-ui/app/rules/CorrelationSidebar/DeleteRule.tsx index feabbeb1d..992a2151c 100644 --- a/keep-ui/app/rules/CorrelationSidebar/DeleteRule.tsx +++ b/keep-ui/app/rules/CorrelationSidebar/DeleteRule.tsx @@ -1,6 +1,6 @@ import { TrashIcon } from "@radix-ui/react-icons"; import { Button } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { MouseEvent } from "react"; import { useApiUrl } from "utils/hooks/useConfig"; import { useRules } from "utils/hooks/useRules"; diff --git a/keep-ui/app/settings/auth/permissions-tab.tsx b/keep-ui/app/settings/auth/permissions-tab.tsx index 6a98e5445..702b00811 100644 --- a/keep-ui/app/settings/auth/permissions-tab.tsx +++ b/keep-ui/app/settings/auth/permissions-tab.tsx @@ -10,7 +10,7 @@ import Loading from "app/loading"; import { PermissionsTable } from "./permissions-table"; import PermissionSidebar from "./permissions-sidebar"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; interface Props { accessToken: string; diff --git a/keep-ui/app/settings/auth/users-sidebar.tsx b/keep-ui/app/settings/auth/users-sidebar.tsx index 7c5752ed5..b485ec6af 100644 --- a/keep-ui/app/settings/auth/users-sidebar.tsx +++ b/keep-ui/app/settings/auth/users-sidebar.tsx @@ -5,8 +5,6 @@ import { Subtitle, Button, TextInput, - SearchSelect, - SearchSelectItem, MultiSelect, MultiSelectItem, Callout, @@ -21,7 +19,7 @@ import { import { useRoles } from "utils/hooks/useRoles"; import { useGroups } from "utils/hooks/useGroups"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { User, Group } from "app/settings/models"; import { AuthenticationType } from "utils/authenticationType"; import { useConfig } from "utils/hooks/useConfig"; @@ -105,7 +103,9 @@ const UsersSidebar = ({ }, [user, setValue, isOpen, reset, clearErrors, identifierType]); const onSubmit: SubmitHandler = async (data) => { - if (!userCreationAllowed) return; + if (!userCreationAllowed) { + return; + } setIsSubmitting(true); clearErrors("root.serverError"); @@ -385,8 +385,8 @@ const UsersSidebar = ({ {isSubmitting ? "Saving..." : isNewUser - ? "Create User" - : "Save"} + ? "Create User" + : "Save"} )} diff --git a/keep-ui/app/settings/settings.client.tsx b/keep-ui/app/settings/settings.client.tsx index 0b8c213b2..36d912a69 100644 --- a/keep-ui/app/settings/settings.client.tsx +++ b/keep-ui/app/settings/settings.client.tsx @@ -11,7 +11,7 @@ import { LockClosedIcon, } from "@heroicons/react/24/outline"; import { MdOutlineSecurity } from "react-icons/md"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useConfig } from "utils/hooks/useConfig"; import { AuthenticationType } from "utils/authenticationType"; @@ -73,24 +73,24 @@ export default function SettingsPage() { newSelectedTab === "users" ? 0 : newSelectedTab === "webhook" - ? 1 - : newSelectedTab === "smtp" - ? 2 - : 0; + ? 1 + : newSelectedTab === "smtp" + ? 2 + : 0; const userSubTabIndex = newUserSubTab === "users" ? 0 : newUserSubTab === "groups" - ? 1 - : newUserSubTab === "roles" - ? 2 - : newUserSubTab === "permissions" - ? 3 - : newUserSubTab === "api-keys" - ? 4 - : newUserSubTab === "sso" - ? 5 - : 0; + ? 1 + : newUserSubTab === "roles" + ? 2 + : newUserSubTab === "permissions" + ? 3 + : newUserSubTab === "api-keys" + ? 4 + : newUserSubTab === "sso" + ? 5 + : 0; setTabIndex(tabIndex); setUserSubTabIndex(userSubTabIndex); setSelectedTab(newSelectedTab); diff --git a/keep-ui/app/topology/model/useTopology.ts b/keep-ui/app/topology/model/useTopology.ts index 41f42354f..b93d42c48 100644 --- a/keep-ui/app/topology/model/useTopology.ts +++ b/keep-ui/app/topology/model/useTopology.ts @@ -1,5 +1,5 @@ import { TopologyService } from "@/app/topology/model/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { fetcher } from "@/utils/fetcher"; import { useEffect } from "react"; diff --git a/keep-ui/app/topology/model/useTopologyApplications.ts b/keep-ui/app/topology/model/useTopologyApplications.ts index eb6c34b61..eb749d254 100644 --- a/keep-ui/app/topology/model/useTopologyApplications.ts +++ b/keep-ui/app/topology/model/useTopologyApplications.ts @@ -2,7 +2,7 @@ import { TopologyApplication } from "./models"; import { useApiUrl } from "utils/hooks/useConfig"; import useSWR, { SWRConfiguration } from "swr"; import { fetcher } from "@/utils/fetcher"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useCallback, useMemo } from "react"; import { useTopologyBaseKey, useTopology } from "./useTopology"; import { useRevalidateMultiple } from "@/utils/state"; diff --git a/keep-ui/app/workflows/[workflow_id]/executions.tsx b/keep-ui/app/workflows/[workflow_id]/executions.tsx index 86df4cd2b..963588fcd 100644 --- a/keep-ui/app/workflows/[workflow_id]/executions.tsx +++ b/keep-ui/app/workflows/[workflow_id]/executions.tsx @@ -1,7 +1,7 @@ "use client"; import { Callout, Card } from "@tremor/react"; import React, { useEffect, useState } from "react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { ExclamationCircleIcon } from "@heroicons/react/24/outline"; import Loading from "app/loading"; import { useRouter } from "next/navigation"; diff --git a/keep-ui/app/workflows/builder/page.client.tsx b/keep-ui/app/workflows/builder/page.client.tsx index 73f9223d2..fd418e388 100644 --- a/keep-ui/app/workflows/builder/page.client.tsx +++ b/keep-ui/app/workflows/builder/page.client.tsx @@ -9,7 +9,7 @@ import { ArrowUpOnSquareIcon, PlayIcon, } from "@heroicons/react/20/solid"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { BuilderCard } from "./builder-card"; import Loading from "../../loading"; diff --git a/keep-ui/app/workflows/builder/workflow-execution-results.tsx b/keep-ui/app/workflows/builder/workflow-execution-results.tsx index b468682e2..5983214b7 100644 --- a/keep-ui/app/workflows/builder/workflow-execution-results.tsx +++ b/keep-ui/app/workflows/builder/workflow-execution-results.tsx @@ -7,7 +7,7 @@ import { Card, Title, } from "@tremor/react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import Loading from "../../loading"; import { ExclamationCircleIcon } from "@heroicons/react/24/outline"; @@ -211,8 +211,8 @@ export function ExecutionResults({ log.message?.includes("NOT to run") ? "bg-red-100" : log.message?.includes("evaluated to run") - ? "bg-green-100" - : "" + ? "bg-green-100" + : "" }`} key={index} > diff --git a/keep-ui/app/workflows/dragndrop.tsx b/keep-ui/app/workflows/dragndrop.tsx index cc7c1d80f..2cf06f9e3 100644 --- a/keep-ui/app/workflows/dragndrop.tsx +++ b/keep-ui/app/workflows/dragndrop.tsx @@ -1,6 +1,6 @@ import React, { useRef, useState } from "react"; import { useApiUrl } from "utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; const FileUpload: React.FC = () => { const apiUrl = useApiUrl(); diff --git a/keep-ui/app/workflows/manual-run-workflow-modal.tsx b/keep-ui/app/workflows/manual-run-workflow-modal.tsx index bd548ae12..825fb9375 100644 --- a/keep-ui/app/workflows/manual-run-workflow-modal.tsx +++ b/keep-ui/app/workflows/manual-run-workflow-modal.tsx @@ -3,7 +3,7 @@ import { Button, Select, SelectItem, Title } from "@tremor/react"; import Modal from "@/components/ui/Modal"; import { useWorkflows } from "utils/hooks/useWorkflows"; import { useState } from "react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "utils/hooks/useConfig"; import { toast } from "react-toastify"; import { useRouter } from "next/navigation"; diff --git a/keep-ui/app/workflows/workflow-tile.tsx b/keep-ui/app/workflows/workflow-tile.tsx index ad9a4e636..636ad7e3d 100644 --- a/keep-ui/app/workflows/workflow-tile.tsx +++ b/keep-ui/app/workflows/workflow-tile.tsx @@ -1,6 +1,6 @@ "use client"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { Workflow, Filter } from "./models"; import { useApiUrl } from "utils/hooks/useConfig"; import Image from "next/image"; diff --git a/keep-ui/app/workflows/workflows.client.tsx b/keep-ui/app/workflows/workflows.client.tsx index 8a5d9e34b..58e53fc30 100644 --- a/keep-ui/app/workflows/workflows.client.tsx +++ b/keep-ui/app/workflows/workflows.client.tsx @@ -8,7 +8,7 @@ import { ExclamationCircleIcon, PlusCircleIcon, } from "@heroicons/react/24/outline"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { fetcher } from "../../utils/fetcher"; import { Workflow, MockWorkflow } from "./models"; import { useApiUrl } from "utils/hooks/useConfig"; diff --git a/keep-ui/entities/incidents/model/useIncidentActions.tsx b/keep-ui/entities/incidents/model/useIncidentActions.tsx index 98d676009..76b3074ad 100644 --- a/keep-ui/entities/incidents/model/useIncidentActions.tsx +++ b/keep-ui/entities/incidents/model/useIncidentActions.tsx @@ -1,5 +1,5 @@ import { useApiUrl } from "@/utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useCallback } from "react"; import { toast } from "react-toastify"; import { useSWRConfig } from "swr"; diff --git a/keep-ui/shared/lib/hooks/useHydratedSession.tsx b/keep-ui/shared/lib/hooks/useHydratedSession.tsx new file mode 100644 index 000000000..6fddec50f --- /dev/null +++ b/keep-ui/shared/lib/hooks/useHydratedSession.tsx @@ -0,0 +1,31 @@ +"use client"; +import { useState, useEffect } from "react"; +import { useSession as useNextAuthSession } from "next-auth/react"; +import type { Session } from "next-auth"; +import type { UseSessionOptions, SessionContextValue } from "next-auth/react"; + +export function useHydratedSession( + options?: UseSessionOptions +): SessionContextValue { + const [isHydrated, setIsHydrated] = useState(false); + const session = useNextAuthSession(options); + useEffect(() => { + setIsHydrated(true); + }, []); + // Ensure we're in browser environment + const isBrowser = typeof window !== "undefined"; + // On first render, return hydrated session if available + if ( + (!isHydrated || session.status === "loading") && + isBrowser && + window.__NEXT_AUTH_SESSION__ !== null && + window.__NEXT_AUTH_SESSION__ !== undefined + ) { + return { + data: window.__NEXT_AUTH_SESSION__, + status: "authenticated" as const, + update: session.update, + } satisfies SessionContextValue; + } + return session; +} diff --git a/keep-ui/shared/ui/PostHogPageView.tsx b/keep-ui/shared/ui/PostHogPageView.tsx index d267f5968..818737a8d 100644 --- a/keep-ui/shared/ui/PostHogPageView.tsx +++ b/keep-ui/shared/ui/PostHogPageView.tsx @@ -5,7 +5,7 @@ import { usePathname, useSearchParams } from "next/navigation"; import { useEffect } from "react"; import { usePostHog } from "posthog-js/react"; import { useConfig } from "@/utils/hooks/useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "../lib/hooks/useHydratedSession"; import { NoAuthUserEmail } from "@/utils/authenticationType"; export default function PostHogPageView(): null { diff --git a/keep-ui/utils/hooks/useAI.ts b/keep-ui/utils/hooks/useAI.ts index 329830b32..80f5f2531 100644 --- a/keep-ui/utils/hooks/useAI.ts +++ b/keep-ui/utils/hooks/useAI.ts @@ -1,5 +1,5 @@ import { AILogs, AIStats } from "app/ai/model"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useAlertQuality.ts b/keep-ui/utils/hooks/useAlertQuality.ts index 9921da550..3445ae923 100644 --- a/keep-ui/utils/hooks/useAlertQuality.ts +++ b/keep-ui/utils/hooks/useAlertQuality.ts @@ -1,9 +1,9 @@ -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import { fetcher } from "../fetcher"; import useSWRImmutable from "swr/immutable"; import { useSearchParams } from "next/navigation"; -import { useMemo } from "react"; +import { useMemo } from "react"; import { useApiUrl } from "./useConfig"; export const useAlertQualityMetrics = ( @@ -19,7 +19,7 @@ export const useAlertQualityMetrics = ( const fieldArray = Array.isArray(fields) ? fields : [fields]; fieldArray.forEach((field) => params.append("fields", field)); } - + return params.toString(); }, [fields, searchParams]); // TODO: Proper type needs to be defined. diff --git a/keep-ui/utils/hooks/useAlerts.ts b/keep-ui/utils/hooks/useAlerts.ts index 4bbe5fd65..6b8abf516 100644 --- a/keep-ui/utils/hooks/useAlerts.ts +++ b/keep-ui/utils/hooks/useAlerts.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useMemo } from "react"; import { AlertDto } from "app/alerts/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useDashboardMetricWidgets.ts b/keep-ui/utils/hooks/useDashboardMetricWidgets.ts index d7d24ecc8..51ab7ba9c 100644 --- a/keep-ui/utils/hooks/useDashboardMetricWidgets.ts +++ b/keep-ui/utils/hooks/useDashboardMetricWidgets.ts @@ -1,7 +1,7 @@ - import {useSession} from "next-auth/react"; - import { useApiUrl } from "./useConfig"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; +import { useApiUrl } from "./useConfig"; import useSWR from "swr"; -import {fetcher} from "@/utils/fetcher"; +import { fetcher } from "@/utils/fetcher"; import { usePathname, useSearchParams } from "next/navigation"; export interface MetricsWidget { @@ -12,7 +12,7 @@ export interface MetricsWidget { interface DistributionData { hour: string; - number: number + number: number; } interface DashboardDistributionData { @@ -20,47 +20,48 @@ interface DashboardDistributionData { ipd: DistributionData[]; apd: DistributionData[]; wpd: DistributionData[]; - } export const useDashboardMetricWidgets = (useFilters?: boolean) => { - const {data: session} = useSession(); + const { data: session } = useSession(); const apiUrl = useApiUrl(); const searchParams = useSearchParams(); const filters = searchParams?.toString(); - const {data, error, mutate} = useSWR( - session ? `${apiUrl}/dashboard/metric-widgets${ - useFilters && filters ? `?${filters}` : "" - }` : null, - (url: string) => fetcher(url, session!.accessToken) - ) - console.log(filters) + const { data, error, mutate } = useSWR( + session + ? `${apiUrl}/dashboard/metric-widgets${ + useFilters && filters ? `?${filters}` : "" + }` + : null, + (url: string) => fetcher(url, session!.accessToken) + ); + console.log(filters); - let widgets: MetricsWidget[] = [] + let widgets: MetricsWidget[] = []; if (data) { - widgets = [ + widgets = [ { id: "mttr", name: "MTTR", - data: data.mttr + data: data.mttr, }, { id: "apd", - "name": "Alerts/Day", - data: data.apd + name: "Alerts/Day", + data: data.apd, }, { id: "ipd", name: "Incidents/Day", - data: data.ipd + data: data.ipd, }, { id: "wpd", name: "Workflows/Day", - data: data.wpd - } + data: data.wpd, + }, ]; } - return {widgets}; -} \ No newline at end of file + return { widgets }; +}; diff --git a/keep-ui/utils/hooks/useDashboardPresets.ts b/keep-ui/utils/hooks/useDashboardPresets.ts index 2f5cd0310..807fd7e1d 100644 --- a/keep-ui/utils/hooks/useDashboardPresets.ts +++ b/keep-ui/utils/hooks/useDashboardPresets.ts @@ -1,16 +1,18 @@ -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { usePresets } from "./usePresets"; import { Preset } from "app/alerts/models"; -import { useMemo } from "react"; +import { useCallback, useMemo } from "react"; import { useSearchParams } from "next/navigation"; export const useDashboardPreset = () => { const { data: session } = useSession(); - const { useAllPresets, useStaticPresets, presetsOrderFromLS, staticPresetsOrderFromLS } = usePresets( - "dashboard", - true - ); + const { + useAllPresets, + useStaticPresets, + presetsOrderFromLS, + staticPresetsOrderFromLS, + } = usePresets("dashboard", true); const { data: presets = [] } = useAllPresets({ revalidateIfStale: false, revalidateOnFocus: false, @@ -20,24 +22,35 @@ export const useDashboardPreset = () => { }); const searchParams = useSearchParams(); - - const checkValidPreset = (preset: Preset) => { - if (!preset.is_private) { - return true; - } - return preset && preset.created_by == session?.user?.email; - }; + const checkValidPreset = useCallback( + (preset: Preset) => { + if (!preset.is_private) { + return true; + } + return preset && preset.created_by == session?.user?.email; + }, + [session] + ); let allPreset = useMemo(() => { /*If any filters are applied on the dashboard, we will fetch live data; otherwise, we will use data from localStorage to sync values between the navbar and the dashboard.*/ - let combinedPresets = searchParams?.toString() ? [...presets, ...fetchedPresets]: [...presetsOrderFromLS, ...staticPresetsOrderFromLS]; + let combinedPresets = searchParams?.toString() + ? [...presets, ...fetchedPresets] + : [...presetsOrderFromLS, ...staticPresetsOrderFromLS]; //private preset checks combinedPresets = combinedPresets.filter((preset) => checkValidPreset(preset) ); return combinedPresets; - }, [presets, fetchedPresets, searchParams, presets, fetchedPresets]); + }, [ + searchParams, + presets, + fetchedPresets, + presetsOrderFromLS, + staticPresetsOrderFromLS, + checkValidPreset, + ]); - return allPreset; + return allPreset; }; diff --git a/keep-ui/utils/hooks/useDashboards.ts b/keep-ui/utils/hooks/useDashboards.ts index 7f3c81245..e3c9e495c 100644 --- a/keep-ui/utils/hooks/useDashboards.ts +++ b/keep-ui/utils/hooks/useDashboards.ts @@ -1,5 +1,5 @@ import useSWR from "swr"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useDeduplicationRules.ts b/keep-ui/utils/hooks/useDeduplicationRules.ts index 54b68015b..74b13fd82 100644 --- a/keep-ui/utils/hooks/useDeduplicationRules.ts +++ b/keep-ui/utils/hooks/useDeduplicationRules.ts @@ -1,5 +1,5 @@ import { DeduplicationRule } from "app/deduplication/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useExtractionRules.ts b/keep-ui/utils/hooks/useExtractionRules.ts index 0ff32b445..4655326a5 100644 --- a/keep-ui/utils/hooks/useExtractionRules.ts +++ b/keep-ui/utils/hooks/useExtractionRules.ts @@ -1,5 +1,5 @@ import { ExtractionRule } from "app/extraction/model"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useGroups.ts b/keep-ui/utils/hooks/useGroups.ts index 3e1dde9a2..fd3c29dae 100644 --- a/keep-ui/utils/hooks/useGroups.ts +++ b/keep-ui/utils/hooks/useGroups.ts @@ -1,5 +1,5 @@ import { Group } from "app/settings/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useIncidents.ts b/keep-ui/utils/hooks/useIncidents.ts index 59ae7353f..c24bdc298 100644 --- a/keep-ui/utils/hooks/useIncidents.ts +++ b/keep-ui/utils/hooks/useIncidents.ts @@ -5,7 +5,7 @@ import { PaginatedIncidentsDto, } from "@/entities/incidents/model"; import { PaginatedWorkflowExecutionDto } from "app/workflows/builder/types"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useMaintenanceRules.ts b/keep-ui/utils/hooks/useMaintenanceRules.ts index b771615b1..f2d3f618b 100644 --- a/keep-ui/utils/hooks/useMaintenanceRules.ts +++ b/keep-ui/utils/hooks/useMaintenanceRules.ts @@ -1,5 +1,5 @@ import { MaintenanceRule } from "app/maintenance/model"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useMappingRules.ts b/keep-ui/utils/hooks/useMappingRules.ts index cf116bc9c..49042ae09 100644 --- a/keep-ui/utils/hooks/useMappingRules.ts +++ b/keep-ui/utils/hooks/useMappingRules.ts @@ -1,5 +1,5 @@ import { MappingRule } from "app/mapping/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/usePermissions.ts b/keep-ui/utils/hooks/usePermissions.ts index b240ec2f6..05307ddc7 100644 --- a/keep-ui/utils/hooks/usePermissions.ts +++ b/keep-ui/utils/hooks/usePermissions.ts @@ -1,5 +1,5 @@ import { Permission } from "app/settings/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/usePresets.ts b/keep-ui/utils/hooks/usePresets.ts index a0a0d76e2..5065c74b9 100644 --- a/keep-ui/utils/hooks/usePresets.ts +++ b/keep-ui/utils/hooks/usePresets.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useRef } from "react"; import { Preset } from "app/alerts/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useProviders.ts b/keep-ui/utils/hooks/useProviders.ts index 668af3a1e..06ad74a4d 100644 --- a/keep-ui/utils/hooks/useProviders.ts +++ b/keep-ui/utils/hooks/useProviders.ts @@ -1,4 +1,4 @@ -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "./useConfig"; import { SWRConfiguration } from "swr"; import { ProvidersResponse } from "app/providers/providers"; diff --git a/keep-ui/utils/hooks/usePusher.ts b/keep-ui/utils/hooks/usePusher.ts index f1b0c23ed..c430ef054 100644 --- a/keep-ui/utils/hooks/usePusher.ts +++ b/keep-ui/utils/hooks/usePusher.ts @@ -1,6 +1,6 @@ import Pusher, { Options as PusherOptions } from "pusher-js"; import { useConfig } from "./useConfig"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "./useConfig"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/keep-ui/utils/hooks/useRoles.ts b/keep-ui/utils/hooks/useRoles.ts index dabfc9b58..cf37634fa 100644 --- a/keep-ui/utils/hooks/useRoles.ts +++ b/keep-ui/utils/hooks/useRoles.ts @@ -1,5 +1,5 @@ import { Role } from "app/settings/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useRules.ts b/keep-ui/utils/hooks/useRules.ts index 97976d51e..add981b45 100644 --- a/keep-ui/utils/hooks/useRules.ts +++ b/keep-ui/utils/hooks/useRules.ts @@ -1,4 +1,4 @@ -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; diff --git a/keep-ui/utils/hooks/useScopes.ts b/keep-ui/utils/hooks/useScopes.ts index 775d8717a..122a2a289 100644 --- a/keep-ui/utils/hooks/useScopes.ts +++ b/keep-ui/utils/hooks/useScopes.ts @@ -1,5 +1,5 @@ import { Scope } from "app/settings/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useSearchAlerts.ts b/keep-ui/utils/hooks/useSearchAlerts.ts index 01de3fe14..9ef8cb0b0 100644 --- a/keep-ui/utils/hooks/useSearchAlerts.ts +++ b/keep-ui/utils/hooks/useSearchAlerts.ts @@ -1,6 +1,6 @@ import useSWR, { SWRConfiguration } from "swr"; import { AlertDto } from "app/alerts/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "./useConfig"; import { fetcher } from "utils/fetcher"; import { useDebouncedValue } from "./useDebouncedValue"; diff --git a/keep-ui/utils/hooks/useTags.ts b/keep-ui/utils/hooks/useTags.ts index 124da6649..7587c386f 100644 --- a/keep-ui/utils/hooks/useTags.ts +++ b/keep-ui/utils/hooks/useTags.ts @@ -1,4 +1,4 @@ -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useUsers.ts b/keep-ui/utils/hooks/useUsers.ts index de254e040..723045071 100644 --- a/keep-ui/utils/hooks/useUsers.ts +++ b/keep-ui/utils/hooks/useUsers.ts @@ -1,5 +1,5 @@ import { User } from "app/settings/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import useSWRImmutable from "swr/immutable"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useWorkflowExecutions.ts b/keep-ui/utils/hooks/useWorkflowExecutions.ts index 8e6fccc27..53fea2d8c 100644 --- a/keep-ui/utils/hooks/useWorkflowExecutions.ts +++ b/keep-ui/utils/hooks/useWorkflowExecutions.ts @@ -3,7 +3,7 @@ import { PaginatedWorkflowExecutionDto, WorkflowExecution, } from "app/workflows/builder/types"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useSearchParams } from "next/navigation"; import useSWR, { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; diff --git a/keep-ui/utils/hooks/useWorkflowRun.ts b/keep-ui/utils/hooks/useWorkflowRun.ts index dbaa98dc8..a645e9f86 100644 --- a/keep-ui/utils/hooks/useWorkflowRun.ts +++ b/keep-ui/utils/hooks/useWorkflowRun.ts @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { useApiUrl } from "./useConfig"; import { useRouter } from "next/navigation"; import { useProviders } from "./useProviders"; diff --git a/keep-ui/utils/hooks/useWorkflows.ts b/keep-ui/utils/hooks/useWorkflows.ts index 26859eaf2..1a8eae55c 100644 --- a/keep-ui/utils/hooks/useWorkflows.ts +++ b/keep-ui/utils/hooks/useWorkflows.ts @@ -1,5 +1,5 @@ import { Workflow } from "app/workflows/models"; -import { useSession } from "next-auth/react"; +import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession"; import { SWRConfiguration } from "swr"; import { useApiUrl } from "./useConfig"; import { fetcher } from "../fetcher";