mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-07-08 21:50:12 +02:00
k
This commit is contained in:
@ -1,6 +0,0 @@
|
|||||||
from fastapi import APIRouter
|
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
# Add production endpoints here
|
|
@ -423,8 +423,7 @@ def get_application() -> FastAPI:
|
|||||||
# NOTE: needs to be outside of the `if __name__ == "__main__"` block so that the
|
# NOTE: needs to be outside of the `if __name__ == "__main__"` block so that the
|
||||||
# app is exportable
|
# app is exportable
|
||||||
set_is_ee_based_on_env_variable()
|
set_is_ee_based_on_env_variable()
|
||||||
# Call get_application() to get the actual application instance
|
app = fetch_versioned_implementation(module="onyx.main", attribute="get_application")
|
||||||
app = fetch_versioned_implementation(module="onyx.main", attribute="get_application")()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -12,6 +12,7 @@ import { getCurrentUser } from "@/lib/user";
|
|||||||
import { usePostHog } from "posthog-js/react";
|
import { usePostHog } from "posthog-js/react";
|
||||||
import { CombinedSettings } from "@/app/admin/settings/interfaces";
|
import { CombinedSettings } from "@/app/admin/settings/interfaces";
|
||||||
import { SettingsContext } from "../settings/SettingsProvider";
|
import { SettingsContext } from "../settings/SettingsProvider";
|
||||||
|
import { useTokenRefresh } from "@/hooks/useTokenRefresh";
|
||||||
|
|
||||||
interface UserContextType {
|
interface UserContextType {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
@ -71,12 +72,6 @@ export function UserProvider({
|
|||||||
mergeUserPreferences(user, settings)
|
mergeUserPreferences(user, settings)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Track last refresh time to avoid unnecessary calls
|
|
||||||
const [lastTokenRefresh, setLastTokenRefresh] = useState<number>(Date.now());
|
|
||||||
|
|
||||||
// Use a ref to track first load
|
|
||||||
const isFirstLoad = useRef(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUpToDateUser(mergeUserPreferences(user, updatedSettings));
|
setUpToDateUser(mergeUserPreferences(user, updatedSettings));
|
||||||
}, [user, updatedSettings]);
|
}, [user, updatedSettings]);
|
||||||
@ -97,74 +92,6 @@ export function UserProvider({
|
|||||||
}
|
}
|
||||||
}, [posthog, user]);
|
}, [posthog, user]);
|
||||||
|
|
||||||
// Implement token refresh mechanism
|
|
||||||
useEffect(() => {
|
|
||||||
if (!upToDateUser) return;
|
|
||||||
|
|
||||||
// Refresh token every 10 minutes (600000ms)
|
|
||||||
// This is shorter than the session expiry time to ensure tokens stay valid
|
|
||||||
const REFRESH_INTERVAL = 600000;
|
|
||||||
|
|
||||||
const refreshTokenPeriodically = async () => {
|
|
||||||
try {
|
|
||||||
// Skip time check if this is first load - we always refresh on first load
|
|
||||||
const isTimeToRefresh =
|
|
||||||
isFirstLoad.current ||
|
|
||||||
Date.now() - lastTokenRefresh > REFRESH_INTERVAL - 60000;
|
|
||||||
|
|
||||||
if (!isTimeToRefresh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset first load flag
|
|
||||||
if (isFirstLoad.current) {
|
|
||||||
isFirstLoad.current = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch("/api/auth/refresh", {
|
|
||||||
method: "POST",
|
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
// Update last refresh time on success
|
|
||||||
setLastTokenRefresh(Date.now());
|
|
||||||
console.debug("Auth token refreshed successfully");
|
|
||||||
} else {
|
|
||||||
console.warn("Failed to refresh auth token:", response.status);
|
|
||||||
// If token refresh fails, try to get current user info
|
|
||||||
await fetchUser();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error refreshing auth token:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Always attempt to refresh on first component mount
|
|
||||||
// This helps ensure tokens are fresh, especially after browser refresh
|
|
||||||
refreshTokenPeriodically();
|
|
||||||
|
|
||||||
// Set up interval for periodic refreshes
|
|
||||||
const intervalId = setInterval(refreshTokenPeriodically, REFRESH_INTERVAL);
|
|
||||||
|
|
||||||
// Also refresh token on window focus, but no more than once per minute
|
|
||||||
const handleVisibilityChange = () => {
|
|
||||||
if (
|
|
||||||
document.visibilityState === "visible" &&
|
|
||||||
Date.now() - lastTokenRefresh > 60000
|
|
||||||
) {
|
|
||||||
refreshTokenPeriodically();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
||||||
};
|
|
||||||
}, [upToDateUser, lastTokenRefresh]);
|
|
||||||
|
|
||||||
const fetchUser = async () => {
|
const fetchUser = async () => {
|
||||||
try {
|
try {
|
||||||
const currentUser = await getCurrentUser();
|
const currentUser = await getCurrentUser();
|
||||||
@ -173,6 +100,10 @@ export function UserProvider({
|
|||||||
console.error("Error fetching current user:", error);
|
console.error("Error fetching current user:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Use the custom token refresh hook
|
||||||
|
useTokenRefresh(upToDateUser, fetchUser);
|
||||||
|
|
||||||
const updateUserTemperatureOverrideEnabled = async (enabled: boolean) => {
|
const updateUserTemperatureOverrideEnabled = async (enabled: boolean) => {
|
||||||
try {
|
try {
|
||||||
setUpToDateUser((prevUser) => {
|
setUpToDateUser((prevUser) => {
|
||||||
|
89
web/src/hooks/useTokenRefresh.ts
Normal file
89
web/src/hooks/useTokenRefresh.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { useState, useEffect, useRef } from "react";
|
||||||
|
import { User } from "@/lib/types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom hook for handling JWT token refresh
|
||||||
|
*
|
||||||
|
* @param user The current user or null if not logged in
|
||||||
|
* @param onRefreshFail Callback function to execute if token refresh fails
|
||||||
|
* @returns Object containing the last token refresh timestamp
|
||||||
|
*/
|
||||||
|
export function useTokenRefresh(
|
||||||
|
user: User | null,
|
||||||
|
onRefreshFail: () => Promise<void>
|
||||||
|
) {
|
||||||
|
// Track last refresh time to avoid unnecessary calls
|
||||||
|
const [lastTokenRefresh, setLastTokenRefresh] = useState<number>(Date.now());
|
||||||
|
|
||||||
|
// Use a ref to track first load
|
||||||
|
const isFirstLoad = useRef(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
// Refresh token every 10 minutes (600000ms)
|
||||||
|
// This is shorter than the session expiry time to ensure tokens stay valid
|
||||||
|
const REFRESH_INTERVAL = 600000;
|
||||||
|
|
||||||
|
const refreshTokenPeriodically = async () => {
|
||||||
|
try {
|
||||||
|
// Skip time check if this is first load - we always refresh on first load
|
||||||
|
const isTimeToRefresh =
|
||||||
|
isFirstLoad.current ||
|
||||||
|
Date.now() - lastTokenRefresh > REFRESH_INTERVAL - 60000;
|
||||||
|
|
||||||
|
if (!isTimeToRefresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset first load flag
|
||||||
|
if (isFirstLoad.current) {
|
||||||
|
isFirstLoad.current = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch("/api/auth/refresh", {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
// Update last refresh time on success
|
||||||
|
setLastTokenRefresh(Date.now());
|
||||||
|
console.debug("Auth token refreshed successfully");
|
||||||
|
} else {
|
||||||
|
console.warn("Failed to refresh auth token:", response.status);
|
||||||
|
// If token refresh fails, try to get current user info
|
||||||
|
await onRefreshFail();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error refreshing auth token:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Always attempt to refresh on first component mount
|
||||||
|
// This helps ensure tokens are fresh, especially after browser refresh
|
||||||
|
refreshTokenPeriodically();
|
||||||
|
|
||||||
|
// Set up interval for periodic refreshes
|
||||||
|
const intervalId = setInterval(refreshTokenPeriodically, REFRESH_INTERVAL);
|
||||||
|
|
||||||
|
// Also refresh token on window focus, but no more than once per minute
|
||||||
|
const handleVisibilityChange = () => {
|
||||||
|
if (
|
||||||
|
document.visibilityState === "visible" &&
|
||||||
|
Date.now() - lastTokenRefresh > 60000
|
||||||
|
) {
|
||||||
|
refreshTokenPeriodically();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
};
|
||||||
|
}, [user, lastTokenRefresh, onRefreshFail]);
|
||||||
|
|
||||||
|
return { lastTokenRefresh };
|
||||||
|
}
|
Reference in New Issue
Block a user