mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-28 05:01:57 +08:00

* chore: update auth * chore: password changes * chore: make changes in oss code * chore: login * chore: get to a running state * fix: migration inital commit * fix: signoz cloud intgtn tests * fix: minor fixes * chore: sso code fixed with org domain * fix: tests * fix: ee auth api's * fix: changes in name * fix: return user in login api * fix: address comments * fix: validate password * fix: handle get domain by email properly * fix: move authomain to usermodule * fix: use displayname instead of hname * fix: rename back endpoints * fix: update telemetry * fix: correct errors * fix: test and fix the invite endpoints * fix: delete all things related to user in store * fix: address issues * fix: ee delete invite * fix: rename func * fix: update user and update role * fix: update role * chore(api): update the api folder structure according to rest principles * fix: login and invite changes * chore(api): update the api folder structure according to rest principles * chore(login): update the frontend according to the new APIs * fix: return org name in users response * chore(login): update the frontend according to the new APIs * fix: update user role * fix: nil check * chore(login): update the frontend according to the new API * fix: getinvite and update role * fix: sso * fix: getinvite use sso ctx * fix: use correct sourceurl * fix: getsourceurl from req payload * chore(login): update the frontend according to the new API * fix: update created_at * fix: fix reset password * chore(login): fixed reset password and bulk invites * fix: sso signup and token password change * fix: don't delete last admin * fix: reset password and migration * fix: migration * chore(login): fix the unwanted throw statement and tsconfig * fix: reset password for sso users * fix: clean up invite * chore(login): delete last admin user and reset password * fix: migration * fix: update claims and store code * fix: use correct error * fix: proper nil checks * fix: make migration multitenant * fix: address comments * fix: minor fixes * fix: test * fix: rename reset password * fix: set self restration only when sso endabled * chore(auth): update the invite user API * fix: integration tests * fix: integration tests * fix: integration tests * fix: integration tests * fix: integration tests * fix: integration tests * fix: integration tests * chore(auth): update integration test * fix: telemetry --------- Co-authored-by: nityanandagohain <nityanandagohain@gmail.com>
197 lines
5.5 KiB
TypeScript
197 lines
5.5 KiB
TypeScript
import { apiV3 } from 'api/apiV1';
|
|
import getLocalStorageApi from 'api/browser/localstorage/get';
|
|
import { Logout } from 'api/utils';
|
|
import loginApi from 'api/v1/login/login';
|
|
import afterLogin from 'AppRoutes/utils';
|
|
import { ENVIRONMENT } from 'constants/env';
|
|
import { LIVE_TAIL_HEARTBEAT_TIMEOUT } from 'constants/liveTail';
|
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
|
import { EventListener, EventSourcePolyfill } from 'event-source-polyfill';
|
|
import { useNotifications } from 'hooks/useNotifications';
|
|
import {
|
|
createContext,
|
|
PropsWithChildren,
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState,
|
|
} from 'react';
|
|
import APIError from 'types/api/error';
|
|
|
|
interface IEventSourceContext {
|
|
eventSourceInstance: EventSourcePolyfill | null;
|
|
isConnectionOpen: boolean;
|
|
isConnectionLoading: boolean;
|
|
isConnectionError: boolean;
|
|
initialLoading: boolean;
|
|
reconnectDueToError: boolean;
|
|
handleStartOpenConnection: (urlProps: {
|
|
url?: string;
|
|
queryString: string;
|
|
}) => void;
|
|
handleCloseConnection: () => void;
|
|
handleSetInitialLoading: (value: boolean) => void;
|
|
}
|
|
|
|
const EventSourceContext = createContext<IEventSourceContext>({
|
|
eventSourceInstance: null,
|
|
isConnectionOpen: false,
|
|
isConnectionLoading: false,
|
|
initialLoading: true,
|
|
isConnectionError: false,
|
|
reconnectDueToError: false,
|
|
handleStartOpenConnection: () => {},
|
|
handleCloseConnection: () => {},
|
|
handleSetInitialLoading: () => {},
|
|
});
|
|
|
|
export function EventSourceProvider({
|
|
children,
|
|
}: PropsWithChildren): JSX.Element {
|
|
const [isConnectionOpen, setIsConnectionOpen] = useState<boolean>(false);
|
|
const [isConnectionLoading, setIsConnectionLoading] = useState<boolean>(false);
|
|
const [isConnectionError, setIsConnectionError] = useState<boolean>(false);
|
|
|
|
const [reconnectDueToError, setReconnectDueToError] = useState<boolean>(false);
|
|
|
|
const [initialLoading, setInitialLoading] = useState<boolean>(true);
|
|
|
|
const eventSourceRef = useRef<EventSourcePolyfill | null>(null);
|
|
|
|
const { notifications } = useNotifications();
|
|
|
|
const handleSetInitialLoading = useCallback((value: boolean) => {
|
|
setInitialLoading(value);
|
|
}, []);
|
|
|
|
const handleOpenConnection: EventListener = useCallback(() => {
|
|
setIsConnectionLoading(false);
|
|
setIsConnectionOpen(true);
|
|
setInitialLoading(false);
|
|
}, []);
|
|
|
|
const handleErrorConnection: EventListener = useCallback(async () => {
|
|
setIsConnectionOpen(false);
|
|
setIsConnectionLoading(true);
|
|
setInitialLoading(false);
|
|
|
|
try {
|
|
const response = await loginApi({
|
|
refreshToken: getLocalStorageApi(LOCALSTORAGE.REFRESH_AUTH_TOKEN) || '',
|
|
});
|
|
afterLogin(
|
|
response.data.userId,
|
|
response.data.accessJwt,
|
|
response.data.refreshJwt,
|
|
true,
|
|
);
|
|
// If token refresh was successful, we'll let the component
|
|
// handle reconnection through the reconnectDueToError state
|
|
setReconnectDueToError(true);
|
|
setIsConnectionError(true);
|
|
return;
|
|
} catch (error) {
|
|
// If there was an error during token refresh, we'll just
|
|
// let the component handle the error state
|
|
notifications.error({
|
|
message: (error as APIError).getErrorCode(),
|
|
description: (error as APIError).getErrorMessage(),
|
|
});
|
|
setIsConnectionError(true);
|
|
if (!eventSourceRef.current) return;
|
|
eventSourceRef.current.close();
|
|
Logout();
|
|
}
|
|
}, [notifications]);
|
|
|
|
const destroyEventSourceSession = useCallback(() => {
|
|
if (!eventSourceRef.current) return;
|
|
|
|
eventSourceRef.current.close();
|
|
eventSourceRef.current.removeEventListener('error', handleErrorConnection);
|
|
eventSourceRef.current.removeEventListener('open', handleOpenConnection);
|
|
}, [handleErrorConnection, handleOpenConnection]);
|
|
|
|
const handleCloseConnection = useCallback(() => {
|
|
setIsConnectionOpen(false);
|
|
setIsConnectionLoading(false);
|
|
setIsConnectionError(false);
|
|
|
|
destroyEventSourceSession();
|
|
}, [destroyEventSourceSession]);
|
|
|
|
const handleStartOpenConnection = useCallback(
|
|
(urlProps: { url?: string; queryString: string }): void => {
|
|
const { url, queryString } = urlProps;
|
|
|
|
const eventSourceUrl = url
|
|
? `${url}/?${queryString}`
|
|
: `${ENVIRONMENT.baseURL}${apiV3}logs/livetail?${queryString}`;
|
|
|
|
eventSourceRef.current = new EventSourcePolyfill(eventSourceUrl, {
|
|
headers: {
|
|
Authorization: `Bearer ${getLocalStorageApi(LOCALSTORAGE.AUTH_TOKEN)}`,
|
|
},
|
|
heartbeatTimeout: LIVE_TAIL_HEARTBEAT_TIMEOUT,
|
|
});
|
|
|
|
setIsConnectionLoading(true);
|
|
setIsConnectionError(false);
|
|
setReconnectDueToError(false);
|
|
|
|
eventSourceRef.current.addEventListener('error', handleErrorConnection);
|
|
eventSourceRef.current.addEventListener('open', handleOpenConnection);
|
|
},
|
|
[handleErrorConnection, handleOpenConnection],
|
|
);
|
|
|
|
useEffect(
|
|
() => (): void => {
|
|
handleCloseConnection();
|
|
},
|
|
[handleCloseConnection],
|
|
);
|
|
|
|
const contextValue: IEventSourceContext = useMemo(
|
|
() => ({
|
|
eventSourceInstance: eventSourceRef.current,
|
|
isConnectionError,
|
|
isConnectionLoading,
|
|
isConnectionOpen,
|
|
initialLoading,
|
|
reconnectDueToError,
|
|
handleStartOpenConnection,
|
|
handleCloseConnection,
|
|
handleSetInitialLoading,
|
|
}),
|
|
[
|
|
isConnectionError,
|
|
isConnectionLoading,
|
|
isConnectionOpen,
|
|
initialLoading,
|
|
reconnectDueToError,
|
|
handleStartOpenConnection,
|
|
handleCloseConnection,
|
|
handleSetInitialLoading,
|
|
],
|
|
);
|
|
|
|
return (
|
|
<EventSourceContext.Provider value={contextValue}>
|
|
{children}
|
|
</EventSourceContext.Provider>
|
|
);
|
|
}
|
|
|
|
export const useEventSource = (): IEventSourceContext => {
|
|
const context = useContext(EventSourceContext);
|
|
|
|
if (!context) {
|
|
throw new Error('Should be used inside the context');
|
|
}
|
|
|
|
return context;
|
|
};
|