mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
* fix: useOAuthClient support OAuth 2.0 * fix: cannot read properties of undefined (reading NEXT_PUBLIC_IS_E2E) * fix: allow OAuth 2.0 token to connect gcal or ms calendar * fix: allow OAuth 2.0 token to save gcal or ms calendar credentials * refactor: dont set oauth id header for OAuth 2.0 * fix: calendar events not showing and emails not sent * feat: CalOAuth2Provider * chore: make OAuth 2.0 work in examples app * chore: refresh OAuth 2.0 tokens * docs: running examples app with oauth 2.0 * fix: remove sensitive console.log statements that leak secrets Remove logging of: - OAuth authorization codes (oauth2-user.ts) - Token-bearing exchange responses (oauth2-user.ts) - /me response data containing PII (oauth2-user.ts) - OAuth2 refresh response with tokens (refresh.ts) - Response payload with access tokens (_app.tsx) Addresses Cubic AI review feedback for issues with confidence >= 9/10 Co-Authored-By: unknown <> * docs: update readme * fix: implemente cubic feedback * fix: seed script import * fix: seed script pkce * fix: correct typos and SQLite capitalization in OAuth2 README (#27176) Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com> * refactor: dont return name in public oauth endpoint * docs: CalOAuthProvider * chore: add NEXT_PUBLIC_IS_E2E constant to test * docs: fix duplicated 'or' in Cal OAuth Provider documentation (#27177) Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com> * revert: is e2e constant * fix: typecheck * refactor: example app users select * update readme * chore: update oauth atoms readme * refactor: enable booking managed event types with user.username instead of profile.username * fix: EventTypeSettings when viewing round robin * test: add e2e tests for atoms-oauth2 controller Co-Authored-By: [email protected] <[email protected]> * fix: correct error message path in atoms-oauth2 e2e test Co-Authored-By: [email protected] <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Rajiv Sahal <[email protected]>
113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
"use client";
|
|
|
|
import { VERSION_2024_06_14 } from "@calcom/platform-constants";
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
import { isAxiosError } from "axios";
|
|
import { useEffect } from "react";
|
|
import http from "../lib/http";
|
|
import type { BaseCalProviderProps } from "./BaseCalProvider";
|
|
import { BaseCalProvider } from "./BaseCalProvider";
|
|
import type { translationKeys } from "./languages";
|
|
|
|
function isRetryableError(error: unknown): boolean {
|
|
if (!isAxiosError(error) || !error.response) {
|
|
// network errors or timeouts — retryable
|
|
return true;
|
|
}
|
|
const status = error.response.status;
|
|
// retry on 408 (timeout), 429 (rate limit), and 5xx (server errors)
|
|
return status === 408 || status === 429 || status >= 500;
|
|
}
|
|
|
|
const queryClient: QueryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
retry: (failureCount: number, error: unknown): boolean => {
|
|
if (!isRetryableError(error)) return false;
|
|
return failureCount < 3;
|
|
},
|
|
retryDelay: (attempt: number) => Math.min(1000 * 2 ** attempt, 30000),
|
|
},
|
|
mutations: {
|
|
retry: (failureCount: number, error: unknown): boolean => {
|
|
if (!isRetryableError(error)) return false;
|
|
return failureCount < 1;
|
|
},
|
|
retryDelay: (attempt: number) => Math.min(1000 * 2 ** attempt, 30000),
|
|
},
|
|
},
|
|
});
|
|
|
|
type CalProviderProps = Omit<BaseCalProviderProps, "isOAuth2">;
|
|
|
|
/**
|
|
* Renders a CalProvider component.
|
|
*
|
|
* @component
|
|
* @param {string} props.clientId - The platform oauth client ID.
|
|
* @param {string} props.accessToken - The access token of your managed user. - Optional
|
|
* @param {object} props.options - The options object.
|
|
* @param {string} [options.apiUrl] - The API URL. https://api.cal.com/v2
|
|
* @param {string} [options.refreshUrl] - The url point to your refresh endpoint. - Optional, required if accessToken is provided.
|
|
* @param {boolean} [autoUpdateTimezone=true] - Whether to automatically update the timezone. - Optional
|
|
* @param {function} props.onTimezoneChange - The callback function for timezone change. - Optional
|
|
* @param {function} props.onTokenRefreshStart - The callback function called when token refresh starts. - Optional
|
|
* @param {function} props.onTokenRefreshSuccess - The callback function called when token refresh succeeds. - Optional
|
|
* @param {function} props.onTokenRefreshError - The callback function called when token refresh fails. - Optional
|
|
* @param {ReactNode} props.children - The child components. - Optional
|
|
* @returns {JSX.Element} The rendered CalProvider component.
|
|
*/
|
|
export function CalProvider({
|
|
clientId,
|
|
accessToken,
|
|
options,
|
|
children,
|
|
autoUpdateTimezone = true,
|
|
labels,
|
|
language = "en",
|
|
onTimezoneChange,
|
|
onTokenRefreshStart,
|
|
onTokenRefreshSuccess,
|
|
onTokenRefreshError,
|
|
version = VERSION_2024_06_14,
|
|
organizationId,
|
|
isEmbed = false,
|
|
}: CalProviderProps): JSX.Element {
|
|
useEffect(() => {
|
|
http.setVersionHeader(version);
|
|
}, [version]);
|
|
|
|
useEffect(() => {
|
|
if (accessToken) {
|
|
queryClient.resetQueries();
|
|
}
|
|
}, [accessToken]);
|
|
|
|
useEffect(() => {
|
|
http.setPlatformEmbedHeader(isEmbed);
|
|
}, [isEmbed]);
|
|
|
|
return (
|
|
<QueryClientProvider client={queryClient}>
|
|
<BaseCalProvider
|
|
isEmbed={isEmbed}
|
|
isOAuth2={false}
|
|
autoUpdateTimezone={autoUpdateTimezone}
|
|
onTimezoneChange={onTimezoneChange}
|
|
onTokenRefreshStart={onTokenRefreshStart}
|
|
onTokenRefreshSuccess={onTokenRefreshSuccess}
|
|
onTokenRefreshError={onTokenRefreshError}
|
|
clientId={clientId}
|
|
accessToken={accessToken}
|
|
options={options}
|
|
version={version}
|
|
labels={labels as Record<translationKeys, string>}
|
|
language={language}
|
|
organizationId={organizationId}
|
|
>
|
|
{children}
|
|
</BaseCalProvider>
|
|
</QueryClientProvider>
|
|
);
|
|
}
|