refactor: clean up auth-related types+utils+functions+hooks into lib/auth/ directory (#12853)

This commit is contained in:
Raunak Bhagat authored and GitHub committed 2026-07-10 19:16:09 +00:00
1 parent 698d0305fd
commit 68cd608f26
27 files changed
+272 -268

No files matched your search

@@ -4,7 +4,7 @@ import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { useUser } from "@/providers/UserProvider";
import { useAuthType } from "@/lib/hooks";
import { AuthType } from "@/lib/constants";
import { AuthType } from "@/lib/auth/types";
import { AccountsAccessSettings } from "@/views/SettingsPage";
export default function AccountsAccessPage() {
+1 -2
View File
@@ -1,13 +1,12 @@
import { User } from "@/lib/types";
import { getCurrentUserSS } from "@/lib/users/svcSS";
import { getAuthTypeMetadataSS, getAuthUrlSS } from "@/lib/auth/svcSS";
import { AuthTypeMetadata } from "@/lib/auth/types";
import { AuthType, AuthTypeMetadata } from "@/lib/auth/types";
import { redirect } from "next/navigation";
import EmailPasswordForm from "../login/EmailPasswordForm";
import SignInButton from "@/app/auth/login/SignInButton";
import AuthFlowContainer from "@/components/auth/AuthFlowContainer";
import AuthErrorDisplay from "@/components/auth/AuthErrorDisplay";
import { AuthType } from "@/lib/constants";
const Page = async (props: {
searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
+3 -3
View File
@@ -1,12 +1,12 @@
"use client";
import { AuthTypeMetadata } from "@/lib/auth/types";
import { AuthType, AuthTypeMetadata } from "@/lib/auth/types";
import LoginText from "@/app/auth/login/LoginText";
import SignInButton from "@/app/auth/login/SignInButton";
import ProviderSignInButton from "@/app/auth/login/ProviderSignInButton";
import EmailPasswordForm from "./EmailPasswordForm";
import { AuthType, NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
import { useSendAuthRequiredMessage } from "@/lib/extension/utils";
import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
import { useSendAuthRequiredMessage } from "@/lib/extension/hooks";
import Text from "@/refresh-components/texts/Text";
import { Button, MessageCard } from "@opal/components";
+1 -1
View File
@@ -28,7 +28,7 @@
import { useState } from "react";
import { Button } from "@opal/components";
import { AuthType } from "@/lib/constants";
import { AuthType } from "@/lib/auth/types";
import { FcGoogle } from "react-icons/fc";
import type { IconProps } from "@opal/types";
import { useCaptcha } from "@/lib/hooks/useCaptcha";
+1 -2
View File
@@ -1,12 +1,11 @@
import { User } from "@/lib/types";
import { getCurrentUserSS } from "@/lib/users/svcSS";
import { getAuthTypeMetadataSS, getAuthUrlSS } from "@/lib/auth/svcSS";
import { AuthTypeMetadata } from "@/lib/auth/types";
import { AuthType, AuthTypeMetadata } from "@/lib/auth/types";
import { redirect } from "next/navigation";
import type { Route } from "next";
import AuthFlowContainer from "@/components/auth/AuthFlowContainer";
import LoginPage from "./LoginPage";
import { AuthType } from "@/lib/constants";
export interface PageProps {
searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
+1 -2
View File
@@ -1,7 +1,7 @@
import { User } from "@/lib/types";
import { getCurrentUserSS } from "@/lib/users/svcSS";
import { getAuthTypeMetadataSS, getAuthUrlSS } from "@/lib/auth/svcSS";
import { AuthTypeMetadata } from "@/lib/auth/types";
import { AuthType, AuthTypeMetadata } from "@/lib/auth/types";
import { redirect } from "next/navigation";
import EmailPasswordForm from "../login/EmailPasswordForm";
import SignInButton from "@/app/auth/login/SignInButton";
@@ -10,7 +10,6 @@ import ReferralSourceSelector from "./ReferralSourceSelector";
import AuthErrorDisplay from "@/components/auth/AuthErrorDisplay";
import Text from "@/refresh-components/texts/Text";
import { cn } from "@opal/utils";
import { AuthType } from "@/lib/constants";
const Page = async (props: {
searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
+4 -3
View File
@@ -4,19 +4,20 @@ import { useState, useEffect, useRef, useCallback, useMemo } from "react";
import { useSearchParams } from "next/navigation";
import { useUser } from "@/providers/UserProvider";
import { toast } from "@/hooks/useToast";
import { AuthType } from "@/lib/constants";
import { AuthType } from "@/lib/auth/types";
import AppInputBar, { AppInputBarHandle } from "@/sections/input/AppInputBar";
import { Button } from "@opal/components";
import Modal from "@/refresh-components/Modal";
import { useFilters, useLlmManager } from "@/lib/hooks";
import Dropzone from "react-dropzone";
import { useSendMessageToParent, getPanelOrigin } from "@/lib/extension/utils";
import { getPanelOrigin } from "@/lib/extension/utils";
import { sendSetDefaultNewTabMessage } from "@/lib/extension/svc";
import { useSendMessageToParent } from "@/lib/extension/hooks";
import { useNRFPreferences } from "@/components/context/NRFPreferencesContext";
import SidePanelHeader from "@/app/nrf/side-panel/SidePanelHeader";
import { CHROME_MESSAGE } from "@/lib/extension/constants";
import { SettingsPanel } from "@/app/components/nrf/SettingsPanel";
import LoginPage from "@/app/auth/login/LoginPage";
import { sendSetDefaultNewTabMessage } from "@/lib/extension/utils";
import { useAgents } from "@/lib/agents/hooks";
import { useProjectsContext } from "@/providers/ProjectsContext";
import useDeepResearchToggle from "@/hooks/useDeepResearchToggle";
-64
View File
@@ -1,64 +0,0 @@
import useSWR from "swr";
import { AuthType, NEXT_PUBLIC_CLOUD_ENABLED } from "@/lib/constants";
import { SWR_KEYS } from "@/lib/swr-keys";
import { AuthTypeMetadata } from "@/lib/auth/types";
interface AuthTypeAPIResponse {
auth_type: string;
requires_verification: boolean;
anonymous_user_enabled: boolean | null;
password_min_length: number;
has_users: boolean;
oauth_enabled: boolean;
}
const DEFAULT_AUTH_TYPE_METADATA: AuthTypeMetadata = {
authType: NEXT_PUBLIC_CLOUD_ENABLED ? AuthType.CLOUD : AuthType.BASIC,
autoRedirect: false,
requiresVerification: false,
anonymousUserEnabled: null,
passwordMinLength: 0,
hasUsers: false,
oauthEnabled: false,
};
async function fetchAuthTypeMetadata(url: string): Promise<AuthTypeMetadata> {
const res = await fetch(url);
if (!res.ok) throw new Error("Failed to fetch auth type metadata");
const data: AuthTypeAPIResponse = await res.json();
const authType = NEXT_PUBLIC_CLOUD_ENABLED
? AuthType.CLOUD
: (data.auth_type as AuthType);
return {
authType,
autoRedirect: authType === AuthType.OIDC || authType === AuthType.SAML,
requiresVerification: data.requires_verification,
anonymousUserEnabled: data.anonymous_user_enabled,
passwordMinLength: data.password_min_length,
hasUsers: data.has_users,
oauthEnabled: data.oauth_enabled,
};
}
export function useAuthTypeMetadata(): {
authTypeMetadata: AuthTypeMetadata;
isLoading: boolean;
error: Error | undefined;
} {
const { data, error, isLoading } = useSWR<AuthTypeMetadata>(
SWR_KEYS.authType,
fetchAuthTypeMetadata,
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false,
dedupingInterval: 30_000,
}
);
return {
authTypeMetadata: data ?? DEFAULT_AUTH_TYPE_METADATA,
isLoading,
error,
};
}
-97
View File
@@ -1,97 +0,0 @@
"use client";
import { useEffect, useRef } from "react";
import { User } from "@/lib/types";
import { NO_AUTH_USER_ID } from "@/lib/extension/constants";
import { AuthTypeMetadata } from "@/lib/auth/types";
import { AuthType } from "@/lib/constants";
const REFRESH_INTERVAL = 600000;
const MIN_REFRESH_GAP_MS = REFRESH_INTERVAL - 60000;
const VISIBILITY_REFRESH_GAP_MS = 60000;
export function useTokenRefresh(
user: User | null,
authTypeMetadata: AuthTypeMetadata,
authTypeMetadataLoading: boolean,
onRefreshFail: () => Promise<void>
) {
// Refs (not state) so updates do not retrigger the effect. lastAttemptRef
// is bumped on every attempt — including failures — so that a 404 cannot
// compound into a re-render loop with the gate permanently open.
const lastAttemptRef = useRef<number>(Date.now());
const isFirstLoadRef = useRef(true);
useEffect(() => {
// The SWR fallback for auth type defaults to BASIC; bail until the real
// value loads, otherwise SAML/OIDC users will hit /api/auth/refresh
// (which is not registered for those auth types) and 404.
if (authTypeMetadataLoading) return;
if (
!user ||
user.id === NO_AUTH_USER_ID ||
// Anonymous users have no session to refresh; a failed refresh churns the
// /me query and can bounce them to login.
user.is_anonymous_user ||
authTypeMetadata.authType === AuthType.OIDC ||
authTypeMetadata.authType === AuthType.SAML
) {
return;
}
const refreshTokenPeriodically = async () => {
const isTimeToRefresh =
isFirstLoadRef.current ||
Date.now() - lastAttemptRef.current > MIN_REFRESH_GAP_MS;
if (!isTimeToRefresh) return;
isFirstLoadRef.current = false;
lastAttemptRef.current = Date.now();
try {
const response = await fetch("/api/auth/refresh", {
method: "POST",
credentials: "include",
});
if (response.ok) {
console.debug("Auth token refreshed successfully");
} else {
console.warn("Failed to refresh auth token:", response.status);
await onRefreshFail();
}
} catch (error) {
console.error("Error refreshing auth token:", error);
}
};
// Hidden tabs skip refreshes entirely; the visibilitychange handler below
// catches the session up as soon as the user returns.
if (!document.hidden) {
refreshTokenPeriodically();
}
const intervalId = setInterval(() => {
if (document.hidden) return;
refreshTokenPeriodically();
}, REFRESH_INTERVAL);
const handleVisibilityChange = () => {
if (
document.visibilityState === "visible" &&
Date.now() - lastAttemptRef.current > VISIBILITY_REFRESH_GAP_MS
) {
refreshTokenPeriodically();
}
};
document.addEventListener("visibilitychange", handleVisibilityChange);
return () => {
clearInterval(intervalId);
document.removeEventListener("visibilitychange", handleVisibilityChange);
};
}, [user, authTypeMetadata, authTypeMetadataLoading, onRefreshFail]);
}
+3 -7
View File
@@ -1,9 +1,9 @@
"use client";
import { useLayoutEffect } from "react";
import AdminSidebar from "@/sections/sidebar/AdminSidebar";
import { usePathname } from "next/navigation";
import { useSettings } from "@/lib/settings/hooks";
import { useAdminDocumentTitle } from "@/lib/app/hooks";
import { ApplicationStatus } from "@/lib/settings/types";
import { Button, Text } from "@opal/components";
import { markdown } from "@opal/utils";
@@ -22,12 +22,8 @@ export default function AdminChrome({ children }: AdminChromeProps) {
const { setFolded } = useSidebarState();
const { isMobile } = useScreenSize();
const pathname = usePathname();
const { appName, vectorDbEnabled, isLoading, application_status } =
useSettings();
useLayoutEffect(() => {
document.title = `Admin — ${appName}`;
}, [pathname, appName]);
const { vectorDbEnabled, isLoading, application_status } = useSettings();
useAdminDocumentTitle();
// Certain admin panels have their own custom sidebar.
// For those pages, we skip rendering the default `AdminSidebar` and let those individual pages render their own.
+2 -12
View File
@@ -3,7 +3,6 @@
import {
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
@@ -67,7 +66,7 @@ import useAppFocus from "@/hooks/useAppFocus";
import { useQueryController } from "@/providers/QueryControllerProvider";
import { useTierAtLeast } from "@/hooks/useTierAtLeast";
import { Tier } from "@/lib/settings/types";
import { useCustomFooterContent } from "@/lib/app/hooks";
import { useAppDocumentTitle, useCustomFooterContent } from "@/lib/app/hooks";
import { useFullWidthChat } from "@/providers/FullWidthChatProvider";
// ---------------------------------------------------------------------------
@@ -558,16 +557,7 @@ export default function AppChrome({ children }: AppChromeProps) {
const [rightPanel, setRightPanel] = useState<ReactNode>(null);
const appFocus = useAppFocus();
const { appName } = useSettings();
const { currentChatSession } = useChatSessions();
useLayoutEffect(() => {
const appendChatNameToDocumentTitle =
(appFocus.isChat() || appFocus.isSharedChat()) && currentChatSession;
document.title = appendChatNameToDocumentTitle
? `${currentChatSession.name} — ${appName}`
: appName;
}, [currentChatSession?.name, appName, appFocus]);
useAppDocumentTitle();
const { hasBackground, appBackgroundUrl } = useAppBackground();
const { resolvedTheme } = useTheme();
+27
View File
@@ -1,5 +1,11 @@
"use client";
import { useLayoutEffect } from "react";
import { usePathname } from "next/navigation";
import { useSettings } from "@/lib/settings/hooks";
import { APP_SLOGAN } from "@/lib/constants";
import useAppFocus from "@/hooks/useAppFocus";
import useChatSessions from "@/hooks/useChatSessions";
export function useCustomFooterContent(): string {
const settings = useSettings();
@@ -8,3 +14,24 @@ export function useCustomFooterContent(): string {
`[Onyx ${settings.version ?? "dev"}](https://www.onyx.app/) - ${APP_SLOGAN}`
);
}
export function useAppDocumentTitle(): void {
const appFocus = useAppFocus();
const { appName } = useSettings();
const { currentChatSession } = useChatSessions();
useLayoutEffect(() => {
const appendChatNameToDocumentTitle =
(appFocus.isChat() || appFocus.isSharedChat()) && currentChatSession;
document.title = appendChatNameToDocumentTitle
? `${currentChatSession.name} — ${appName}`
: appName;
}, [currentChatSession?.name, appName, appFocus]);
}
export function useAdminDocumentTitle(): void {
const pathname = usePathname();
const { appName } = useSettings();
useLayoutEffect(() => {
document.title = `Admin — ${appName}`;
}, [pathname, appName]);
}
@@ -1,8 +1,7 @@
import { act, renderHook, waitFor } from "@testing-library/react";
import { setDocumentVisibility } from "@tests/setup/test-utils";
import { useTokenRefresh } from "@/hooks/useTokenRefresh";
import { AuthTypeMetadata } from "@/lib/auth/types";
import { AuthType } from "@/lib/constants";
import { useTokenRefresh } from "@/lib/auth/hooks";
import { AuthType, AuthTypeMetadata } from "@/lib/auth/types";
import { User } from "@/lib/types";
const baseAuthMetadata = (authType: AuthType): AuthTypeMetadata => ({
@@ -98,16 +97,12 @@ describe("useTokenRefresh", () => {
await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1));
// Simulate the parent re-render storm that occurs when onRefreshFail
// -> mutateUser produces a new user object identity.
for (let i = 0; i < 10; i++) {
await act(async () => {
rerender({ user: { ...fakeUser } });
});
}
// The time-gate should suppress every follow-up attempt; the original
// bug fired ~one extra call per re-render.
expect(fetchMock).toHaveBeenCalledTimes(1);
});
@@ -124,7 +119,6 @@ describe("useTokenRefresh", () => {
)
);
// No refresh on hidden mount, and none from interval ticks while hidden.
await act(async () => {
jest.advanceTimersByTime(31 * 60 * 1000);
});
+153
View File
@@ -2,6 +2,11 @@
import { useEffect, useRef } from "react";
import { usePathname } from "next/navigation";
import useSWR from "swr";
import { NEXT_PUBLIC_CLOUD_ENABLED } from "@/lib/constants";
import { SWR_KEYS } from "@/lib/swr-keys";
import { NO_AUTH_USER_ID } from "@/lib/extension/constants";
import { AuthType, AuthTypeMetadata } from "@/lib/auth/types";
import { User } from "@/lib/types";
import { getSecondsUntilExpiration } from "@opal/time";
import { logout } from "@/lib/users/svc";
@@ -72,3 +77,151 @@ export function useSessionWatcher(): boolean {
hasSeenAuthenticatedUserRef.current
);
}
// ---------------------------------------------------------------------------
// useAuthTypeMetadata
// ---------------------------------------------------------------------------
interface AuthTypeAPIResponse {
auth_type: string;
requires_verification: boolean;
anonymous_user_enabled: boolean | null;
password_min_length: number;
has_users: boolean;
oauth_enabled: boolean;
}
const DEFAULT_AUTH_TYPE_METADATA: AuthTypeMetadata = {
authType: NEXT_PUBLIC_CLOUD_ENABLED ? AuthType.CLOUD : AuthType.BASIC,
autoRedirect: false,
requiresVerification: false,
anonymousUserEnabled: null,
passwordMinLength: 0,
hasUsers: false,
oauthEnabled: false,
};
async function fetchAuthTypeMetadata(url: string): Promise<AuthTypeMetadata> {
const res = await fetch(url);
if (!res.ok) throw new Error("Failed to fetch auth type metadata");
const data: AuthTypeAPIResponse = await res.json();
const authType = NEXT_PUBLIC_CLOUD_ENABLED
? AuthType.CLOUD
: (data.auth_type as AuthType);
return {
authType,
autoRedirect: authType === AuthType.OIDC || authType === AuthType.SAML,
requiresVerification: data.requires_verification,
anonymousUserEnabled: data.anonymous_user_enabled,
passwordMinLength: data.password_min_length,
hasUsers: data.has_users,
oauthEnabled: data.oauth_enabled,
};
}
export function useAuthTypeMetadata(): {
authTypeMetadata: AuthTypeMetadata;
isLoading: boolean;
error: Error | undefined;
} {
const { data, error, isLoading } = useSWR<AuthTypeMetadata>(
SWR_KEYS.authType,
fetchAuthTypeMetadata,
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false,
dedupingInterval: 30_000,
}
);
return {
authTypeMetadata: data ?? DEFAULT_AUTH_TYPE_METADATA,
isLoading,
error,
};
}
// ---------------------------------------------------------------------------
// useTokenRefresh
// ---------------------------------------------------------------------------
const REFRESH_INTERVAL = 600000;
const MIN_REFRESH_GAP_MS = REFRESH_INTERVAL - 60000;
const VISIBILITY_REFRESH_GAP_MS = 60000;
export function useTokenRefresh(
user: User | null,
authTypeMetadata: AuthTypeMetadata,
authTypeMetadataLoading: boolean,
onRefreshFail: () => Promise<void>
) {
const lastAttemptRef = useRef<number>(Date.now());
const isFirstLoadRef = useRef(true);
useEffect(() => {
if (authTypeMetadataLoading) return;
if (
!user ||
user.id === NO_AUTH_USER_ID ||
user.is_anonymous_user ||
authTypeMetadata.authType === AuthType.OIDC ||
authTypeMetadata.authType === AuthType.SAML
) {
return;
}
const refreshTokenPeriodically = async () => {
const isTimeToRefresh =
isFirstLoadRef.current ||
Date.now() - lastAttemptRef.current > MIN_REFRESH_GAP_MS;
if (!isTimeToRefresh) return;
isFirstLoadRef.current = false;
lastAttemptRef.current = Date.now();
try {
const response = await fetch("/api/auth/refresh", {
method: "POST",
credentials: "include",
});
if (response.ok) {
console.debug("Auth token refreshed successfully");
} else {
console.warn("Failed to refresh auth token:", response.status);
await onRefreshFail();
}
} catch (error) {
console.error("Error refreshing auth token:", error);
}
};
if (!document.hidden) {
refreshTokenPeriodically();
}
const intervalId = setInterval(() => {
if (document.hidden) return;
refreshTokenPeriodically();
}, REFRESH_INTERVAL);
const handleVisibilityChange = () => {
if (
document.visibilityState === "visible" &&
Date.now() - lastAttemptRef.current > VISIBILITY_REFRESH_GAP_MS
) {
refreshTokenPeriodically();
}
};
document.addEventListener("visibilitychange", handleVisibilityChange);
return () => {
clearInterval(intervalId);
document.removeEventListener("visibilitychange", handleVisibilityChange);
};
}, [user, authTypeMetadata, authTypeMetadataLoading, onRefreshFail]);
}
+6 -3
View File
@@ -1,9 +1,12 @@
import { buildUrl, UrlBuilder } from "@/lib/utilsSS";
import { AuthType, NEXT_PUBLIC_CLOUD_ENABLED } from "@/lib/constants";
import { NEXT_PUBLIC_CLOUD_ENABLED } from "@/lib/constants";
import { User, UserRole } from "@/lib/types";
import { getCurrentUserSS } from "@/lib/users/svcSS";
import { AuthTypeMetadata } from "@/lib/auth/types";
import type { SSOProviderType } from "@/lib/auth/types";
import {
AuthType,
AuthTypeMetadata,
type SSOProviderType,
} from "@/lib/auth/types";
export async function getAuthTypeMetadataSS(): Promise<AuthTypeMetadata> {
const res = await fetch(buildUrl("/auth/type"));
+7 -1
View File
@@ -1,4 +1,10 @@
import { AuthType } from "@/lib/constants";
export enum AuthType {
BASIC = "basic",
GOOGLE_OAUTH = "google_oauth",
OIDC = "oidc",
SAML = "saml",
CLOUD = "cloud",
}
export type SSOProviderType = "GOOGLE_OAUTH" | "OIDC" | "SAML";
+2 -8
View File
@@ -1,12 +1,6 @@
export const IS_DEV = process.env.NODE_ENV === "development";
import { AuthType } from "@/lib/auth/types";
export enum AuthType {
BASIC = "basic",
GOOGLE_OAUTH = "google_oauth",
OIDC = "oidc",
SAML = "saml",
CLOUD = "cloud",
}
export const IS_DEV = process.env.NODE_ENV === "development";
export const HOST_URL = process.env.WEB_DOMAIN || "http://localhost:3000";
+19
View File
@@ -0,0 +1,19 @@
"use client";
import { useEffect } from "react";
import {
sendAuthRequiredMessage,
sendMessageToParent,
} from "@/lib/extension/svc";
export function useSendAuthRequiredMessage(): void {
useEffect(() => {
sendAuthRequiredMessage();
}, []);
}
export function useSendMessageToParent(): void {
useEffect(() => {
sendMessageToParent();
}, []);
}
+29
View File
@@ -0,0 +1,29 @@
import { CHROME_MESSAGE } from "@/lib/extension/constants";
import { getPanelOrigin } from "@/lib/extension/utils";
export function sendSetDefaultNewTabMessage(value: boolean): void {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: CHROME_MESSAGE.SET_DEFAULT_NEW_TAB, value },
getPanelOrigin()
);
}
}
export function sendAuthRequiredMessage(): void {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: CHROME_MESSAGE.AUTH_REQUIRED },
getPanelOrigin()
);
}
}
export function sendMessageToParent(): void {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: CHROME_MESSAGE.ONYX_APP_LOADED },
getPanelOrigin()
);
}
}
-40
View File
@@ -1,6 +1,3 @@
import { useEffect } from "react";
import { CHROME_MESSAGE } from "./constants";
export type ExtensionContext = "new_tab" | "side_panel" | null;
// Returns the origin of the Chrome extension panel (our parent frame).
@@ -27,40 +24,3 @@ export function getExtensionContext(): {
}
return { isExtension: false, context: null };
}
export function sendSetDefaultNewTabMessage(value: boolean) {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: CHROME_MESSAGE.SET_DEFAULT_NEW_TAB, value },
getPanelOrigin()
);
}
}
export const sendAuthRequiredMessage = () => {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: CHROME_MESSAGE.AUTH_REQUIRED },
getPanelOrigin()
);
}
};
export const useSendAuthRequiredMessage = () => {
useEffect(() => {
sendAuthRequiredMessage();
}, []);
};
export const sendMessageToParent = () => {
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: CHROME_MESSAGE.ONYX_APP_LOADED },
getPanelOrigin()
);
}
};
export const useSendMessageToParent = () => {
useEffect(() => {
sendMessageToParent();
}, []);
};
+3 -6
View File
@@ -30,16 +30,13 @@ import {
} from "@/lib/languageModels/types";
import { isAnthropic } from "@/lib/languageModels/svc";
import { getSourceMetadataForSources } from "./sources";
import {
AuthType,
DEFAULT_AGENT_ID,
NEXT_PUBLIC_CLOUD_ENABLED,
} from "./constants";
import { DEFAULT_AGENT_ID, NEXT_PUBLIC_CLOUD_ENABLED } from "./constants";
import { AuthType } from "@/lib/auth/types";
import { useUser } from "@/providers/UserProvider";
import { SEARCH_TOOL_ID } from "@/app/app/components/tools/constants";
import { updateTemperatureOverrideForChatSession } from "@/app/app/services/lib";
import { useLLMProviders } from "@/lib/languageModels/hooks";
import { useAuthTypeMetadata } from "@/hooks/useAuthTypeMetadata";
import { useAuthTypeMetadata } from "@/lib/auth/hooks";
import { SWR_KEYS } from "@/lib/swr-keys";
export const usePublicCredentials = () => {
+1 -2
View File
@@ -17,9 +17,8 @@ import {
} from "@/lib/types";
import { usePostHog } from "posthog-js/react";
import { useSettings } from "@/lib/settings/hooks";
import { useTokenRefresh } from "@/hooks/useTokenRefresh";
import { useCurrentUser } from "@/lib/users/hooks";
import { useAuthTypeMetadata } from "@/hooks/useAuthTypeMetadata";
import { useAuthTypeMetadata, useTokenRefresh } from "@/lib/auth/hooks";
import { AuthTypeMetadata } from "@/lib/auth/types";
import {
updateUserPersonalization as persistPersonalization,
+1 -1
View File
@@ -1,11 +1,11 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import {
AuthType,
SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED,
SERVER_SIDE_ONLY__AUTH_TYPE,
SERVER_SIDE_ONLY__AUTH_COOKIE_NAME,
} from "./lib/constants";
import { AuthType } from "@/lib/auth/types";
// Route prefixes that never allow anonymous access, so we fast-fail at the edge
// when no auth cookie is present. "/app" is intentionally excluded: it allows
@@ -37,7 +37,7 @@ import { updateMCPServerStatus, upsertMCPServer } from "@/lib/tools/mcpService";
import { toast } from "@/hooks/useToast";
import { SvgArrowExchange } from "@opal/icons";
import { useAuthType } from "@/lib/hooks";
import { AuthType } from "@/lib/constants";
import { AuthType } from "@/lib/auth/types";
interface MCPAuthenticationModalProps {
mcpServer: MCPServer | null;
@@ -18,7 +18,7 @@ import { OAuthConfig } from "@/lib/tools/interfaces";
import { getOAuthConfig } from "@/lib/oauth/api";
import { SvgArrowExchange } from "@opal/icons";
import { useAuthType } from "@/lib/hooks";
import { AuthType } from "@/lib/constants";
import { AuthType } from "@/lib/auth/types";
export type AuthMethod = "oauth" | "custom-header" | "pt-oauth";
+1 -1
View File
@@ -24,7 +24,7 @@ import { useCurrentUser } from "@/lib/users/hooks";
import NoAgentModal from "@/sections/modals/NoAgentModal";
import PreviewModal from "@/sections/modals/PreviewModal";
import Modal from "@/refresh-components/Modal";
import { useSendMessageToParent } from "@/lib/extension/utils";
import { useSendMessageToParent } from "@/lib/extension/hooks";
import { SUBMIT_MESSAGE_TYPES } from "@/lib/extension/constants";
import { getSourceMetadata } from "@/lib/sources";
import { SourceMetadata } from "@/lib/search/interfaces";
@@ -8,8 +8,8 @@ import IconButton from "@/refresh-components/buttons/IconButton";
import Text from "@/refresh-components/texts/Text";
import Link from "next/link";
import { ADMIN_ROUTES } from "@/lib/admin-routes";
import { useAuthTypeMetadata } from "@/hooks/useAuthTypeMetadata";
import { AuthType } from "@/lib/constants";
import { useAuthTypeMetadata } from "@/lib/auth/hooks";
import { AuthType } from "@/lib/auth/types";
import InviteOnlyCard from "./InviteOnlyCard";
// ---------------------------------------------------------------------------