mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-27 19:25:15 +02:00
Merge pull request #1430 from suryo12/refactor/1362-oauth-typed-contract
refactor(web): centralize OAuth callback cookie contract (fixes #1362)
This commit is contained in:
commit
d53866d87d
3 changed files with 39 additions and 18 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
import { type NextRequest, NextResponse } from "next/server";
|
import { type NextRequest, NextResponse } from "next/server";
|
||||||
|
import { OAUTH_RESULT_COOKIE, type OAuthCallbackResult } from "@/contracts/types/oauth.types";
|
||||||
const OAUTH_RESULT_COOKIE = "connector_oauth_result";
|
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
|
|
@ -9,12 +8,13 @@ export async function GET(
|
||||||
const { search_space_id } = await params;
|
const { search_space_id } = await params;
|
||||||
const searchParams = request.nextUrl.searchParams;
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
|
||||||
const result = JSON.stringify({
|
const payload: OAuthCallbackResult = {
|
||||||
success: searchParams.get("success"),
|
success: searchParams.get("success"),
|
||||||
error: searchParams.get("error"),
|
error: searchParams.get("error"),
|
||||||
connector: searchParams.get("connector"),
|
connector: searchParams.get("connector"),
|
||||||
connectorId: searchParams.get("connectorId"),
|
connectorId: searchParams.get("connectorId"),
|
||||||
});
|
};
|
||||||
|
const result = JSON.stringify(payload);
|
||||||
|
|
||||||
const redirectUrl = new URL(`/dashboard/${search_space_id}/new-chat`, request.url);
|
const redirectUrl = new URL(`/dashboard/${search_space_id}/new-chat`, request.url);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-quer
|
||||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||||
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
||||||
import { searchSourceConnector } from "@/contracts/types/connector.types";
|
import { searchSourceConnector } from "@/contracts/types/connector.types";
|
||||||
|
import { OAUTH_RESULT_COOKIE, parseOAuthCallbackResult } from "@/contracts/types/oauth.types";
|
||||||
import { authenticatedFetch } from "@/lib/auth-utils";
|
import { authenticatedFetch } from "@/lib/auth-utils";
|
||||||
|
import { BACKEND_URL } from "@/lib/env-config";
|
||||||
import {
|
import {
|
||||||
trackConnectorConnected,
|
trackConnectorConnected,
|
||||||
trackConnectorDeleted,
|
trackConnectorDeleted,
|
||||||
|
|
@ -36,15 +38,12 @@ import {
|
||||||
OAUTH_CONNECTORS,
|
OAUTH_CONNECTORS,
|
||||||
OTHER_CONNECTORS,
|
OTHER_CONNECTORS,
|
||||||
} from "../constants/connector-constants";
|
} from "../constants/connector-constants";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
dateRangeSchema,
|
dateRangeSchema,
|
||||||
frequencyMinutesSchema,
|
frequencyMinutesSchema,
|
||||||
parseOAuthAuthResponse,
|
parseOAuthAuthResponse,
|
||||||
validateIndexingConfigState,
|
validateIndexingConfigState,
|
||||||
} from "../constants/connector-popup.schemas";
|
} from "../constants/connector-popup.schemas";
|
||||||
import { BACKEND_URL } from "@/lib/env-config";
|
|
||||||
const OAUTH_RESULT_COOKIE = "connector_oauth_result";
|
|
||||||
|
|
||||||
function readOAuthResultCookie(): string | null {
|
function readOAuthResultCookie(): string | null {
|
||||||
const match = document.cookie
|
const match = document.cookie
|
||||||
|
|
@ -211,17 +210,8 @@ export const useConnectorDialog = () => {
|
||||||
if (!raw || !searchSpaceId) return;
|
if (!raw || !searchSpaceId) return;
|
||||||
clearOAuthResultCookie();
|
clearOAuthResultCookie();
|
||||||
|
|
||||||
let result: {
|
const result = parseOAuthCallbackResult(raw);
|
||||||
success: string | null;
|
if (!result) return;
|
||||||
error: string | null;
|
|
||||||
connector: string | null;
|
|
||||||
connectorId: string | null;
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
result = JSON.parse(raw);
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
const oauthConnector = result.connector
|
const oauthConnector = result.connector
|
||||||
|
|
|
||||||
31
surfsense_web/contracts/types/oauth.types.ts
Normal file
31
surfsense_web/contracts/types/oauth.types.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const OAUTH_RESULT_COOKIE = "connector_oauth_result";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema for the payload written to the `connector_oauth_result` cookie by the
|
||||||
|
* OAuth callback route and read back by the connector dialog hook.
|
||||||
|
*/
|
||||||
|
export const oauthCallbackResultSchema = z.object({
|
||||||
|
success: z.string().nullable(),
|
||||||
|
error: z.string().nullable(),
|
||||||
|
connector: z.string().nullable(),
|
||||||
|
connectorId: z.string().nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type OAuthCallbackResult = z.infer<typeof oauthCallbackResultSchema>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely decode and validate the OAuth callback cookie value. Returns `null`
|
||||||
|
* when the value is not valid JSON or does not match the expected shape.
|
||||||
|
*/
|
||||||
|
export function parseOAuthCallbackResult(raw: string): OAuthCallbackResult | null {
|
||||||
|
let parsed: unknown;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(raw);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const result = oauthCallbackResultSchema.safeParse(parsed);
|
||||||
|
return result.success ? result.data : null;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue