Skip to content

Commit

Permalink
Merge pull request #302 from amam-deriv/amam/oauth-2-logout
Browse files Browse the repository at this point in the history
Amam/oauth-2-logout
  • Loading branch information
farrah-deriv authored Aug 26, 2024
2 parents 62c7488 + 4e6509f commit 833fffe
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 101 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ WORKDIR /app

ENV HUSKY=0

RUN git clone https://github.com/deriv-com/p2p.git .
COPY . .

RUN npm install

Expand Down
10 changes: 6 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { BrowserRouter } from 'react-router-dom';
import { QueryParamProvider } from 'use-query-params';
import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5';
import { AppFooter, AppHeader, DerivIframe, ErrorBoundary } from '@/components';
import { useDerivAnalytics, useRedirectToOauth, useTrackjs } from '@/hooks';
import { useDerivAnalytics, useOAuth, useTrackjs } from '@/hooks';
import AppContent from '@/routes/AppContent';
import { initializeI18n, TranslationProvider } from '@deriv-com/translations';
import { Loader, useDevice } from '@deriv-com/ui';
import { URLConstants } from '@deriv-com/utils';
import useGrowthbookGetFeatureValue from './hooks/custom-hooks/useGrowthbookGetFeatureValue';
import useOAuth2Enabled from './hooks/custom-hooks/useOAuth2Enabled';

const { VITE_CROWDIN_BRANCH_NAME, VITE_PROJECT_NAME, VITE_TRANSLATIONS_CDN_URL } = process.env;
const i18nInstance = initializeI18n({
Expand All @@ -19,14 +20,15 @@ const App = () => {
const [ShouldRedirectToDerivApp, isGBLoaded] = useGrowthbookGetFeatureValue({
featureFlag: 'redirect_to_deriv_app_p2p',
});
const [isOAuth2Enabled] = useOAuth2Enabled();
const { onRenderAuthCheck } = useOAuth();
const { init: initTrackJS } = useTrackjs();
const { isDesktop } = useDevice();
const { redirectToOauth } = useRedirectToOauth();
const { initialise: initDerivAnalytics } = useDerivAnalytics();

initTrackJS();
initDerivAnalytics();
redirectToOauth();
onRenderAuthCheck();

useEffect(() => {
if (isGBLoaded && ShouldRedirectToDerivApp) {
Expand All @@ -42,7 +44,7 @@ const App = () => {
<QueryParamProvider adapter={ReactRouter5Adapter}>
<TranslationProvider defaultLang='EN' i18nInstance={i18nInstance}>
<Suspense fallback={<Loader isFullScreen />}>
<DerivIframe />
{!isOAuth2Enabled && <DerivIframe />}
<AppHeader />
<AppContent />
{isDesktop && <AppFooter />}
Expand Down
17 changes: 5 additions & 12 deletions src/components/AppHeader/AppHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getOauthUrl } from '@/constants';
import { api, useRedirectToOauth } from '@/hooks';
import { api, useOAuth } from '@/hooks';
import { getCurrentRoute } from '@/utils';
import { StandaloneCircleUserRegularIcon } from '@deriv/quill-icons';
import { useAuthData } from '@deriv-com/api-hooks';
Expand All @@ -19,11 +19,11 @@ import './AppHeader.scss';
const AppHeader = () => {
const { isDesktop } = useDevice();
const isEndpointPage = getCurrentRoute() === 'endpoint';
const { redirectToOauth } = useRedirectToOauth();
const { activeLoginid, logout } = useAuthData();
const { activeLoginid } = useAuthData();
const { data: activeAccount } = api.account.useActiveAccount();
const { localize } = useTranslations();
const oauthUrl = getOauthUrl();
const { oAuthLogout } = useOAuth();

const renderAccountSection = () => {
if (!isEndpointPage && !activeAccount) {
Expand All @@ -47,14 +47,7 @@ const AppHeader = () => {
</TooltipMenuIcon>
)}
<AccountSwitcher account={activeAccount!} />
<Button
className='mr-6'
onClick={async () => {
await logout();
redirectToOauth();
}}
size='md'
>
<Button className='mr-6' onClick={oAuthLogout} size='md'>
<Text size='sm' weight='bold'>
{localize('Logout')}
</Text>
Expand All @@ -65,7 +58,7 @@ const AppHeader = () => {

return (
<Button
className='min-w-36'
className='w-36'
color='primary-light'
onClick={() => window.open(oauthUrl, '_self')}
variant='ghost'
Expand Down
9 changes: 4 additions & 5 deletions src/components/AppHeader/MobileMenu/MobileMenuConfig.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentProps, ReactNode } from 'react';
import { ACCOUNT_LIMITS, HELP_CENTRE, RESPONSIBLE } from '@/constants';
import { useLiveChat } from '@/hooks/custom-hooks';
import { useLiveChat, useOAuth } from '@/hooks/custom-hooks';
import {
BrandDerivLogoCoralIcon,
IconTypes,
Expand All @@ -16,7 +16,6 @@ import {
LegacyResponsibleTradingIcon,
LegacyWhatsappIcon,
} from '@deriv/quill-icons';
import { useAuthData } from '@deriv-com/api-hooks';
import { useTranslations } from '@deriv-com/translations';
import { URLConstants } from '@deriv-com/utils';

Expand All @@ -36,7 +35,7 @@ type TMenuConfig = {

export const MobileMenuConfig = () => {
const { localize } = useTranslations();
const { logout } = useAuthData();
const { oAuthLogout } = useOAuth();
const { LiveChatWidget } = useLiveChat();

const menuConfig: TMenuConfig[] = [
Expand Down Expand Up @@ -125,8 +124,8 @@ export const MobileMenuConfig = () => {
as: 'button',
label: localize('Log out'),
LeftComponent: LegacyLogout1pxIcon,
onClick: async () => {
await logout();
onClick: () => {
oAuthLogout();
},
removeBorderBottom: true,
},
Expand Down
42 changes: 36 additions & 6 deletions src/constants/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@ export const DERIV_COM = URLConstants.derivComProduction;
export const HELP_CENTRE = `${URLConstants.derivComProduction}/help-centre/`;
export const RESPONSIBLE = `${URLConstants.derivComProduction}/responsible/`;

export const INTRODUCING_DERIV_P2P_URL =
'https://player.vimeo.com/video/715973569?color&autopause=0&loop=0&muted=0&title=0&portrait=0&autoplay=1&byline=0#t=';

export const HOW_TO_USE_DERIV_P2P_URL =
'https://player.vimeo.com/video/715982928?color&autopause=0&loop=0&muted=0&title=0&portrait=0&autoplay=1&byline=0#t=';

export const HOW_TO_PROTECT_YOURSELF_URL = 'https://blog.deriv.com/posts/how-to-protect-yourself-on-p2p-platforms/';

export const DEFAULT_OAUTH_LOGOUT_URL = 'https://oauth.deriv.com/oauth2/sessions/logout';

export const DEFAULT_OAUTH_ORIGIN_URL = 'https://oauth.deriv.com';

const SocketURL = {
[URLConstants.derivP2pProduction]: 'blue.derivws.com',
[URLConstants.derivP2pStaging]: 'red.derivws.com',
};

export const getOauthUrl = () => {
export const getServerInfo = () => {
const origin = window.location.origin;
const hostname = window.location.hostname;

Expand All @@ -45,6 +57,16 @@ export const getOauthUrl = () => {
const appId = LocalStorageUtils.getValue<string>(LocalStorageConstants.configAppId);
const lang = LocalStorageUtils.getValue<string>(LocalStorageConstants.i18nLanguage);

return {
appId,
lang,
serverUrl,
};
};

export const getOauthUrl = () => {
const { appId, lang, serverUrl } = getServerInfo();

const oauthUrl =
appId && serverUrl
? `https://${serverUrl}/oauth2/authorize?app_id=${appId}&l=${lang ?? 'EN'}&&brand=deriv`
Expand All @@ -53,10 +75,18 @@ export const getOauthUrl = () => {
return oauthUrl;
};

export const INTRODUCING_DERIV_P2P_URL =
'https://player.vimeo.com/video/715973569?color&autopause=0&loop=0&muted=0&title=0&portrait=0&autoplay=1&byline=0#t=';
export const getOAuthLogoutUrl = () => {
const { appId, serverUrl } = getServerInfo();

export const HOW_TO_USE_DERIV_P2P_URL =
'https://player.vimeo.com/video/715982928?color&autopause=0&loop=0&muted=0&title=0&portrait=0&autoplay=1&byline=0#t=';
const oauthUrl = appId && serverUrl ? `https://${serverUrl}/oauth2/sessions/logout` : DEFAULT_OAUTH_LOGOUT_URL;

export const HOW_TO_PROTECT_YOURSELF_URL = 'https://blog.deriv.com/posts/how-to-protect-yourself-on-p2p-platforms/';
return oauthUrl;
};

export const getOAuthOrigin = () => {
const { appId, serverUrl } = getServerInfo();

const oauthUrl = appId && serverUrl ? `https://${serverUrl}` : DEFAULT_OAUTH_ORIGIN_URL;

return oauthUrl;
};
39 changes: 39 additions & 0 deletions src/hooks/custom-hooks/__tests__/useOAuth2Enabled.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { renderHook } from '@testing-library/react';
import useGrowthbookGetFeatureValue from '../useGrowthbookGetFeatureValue';
import useOAuth2Enabled from '../useOAuth2Enabled';

jest.mock('@/constants', () => ({
getServerInfo: jest.fn(() => ({
appId: '111', // emulate local appId
})),
}));

jest.mock('../useGrowthbookGetFeatureValue');

describe('useOAuth2Enabled', () => {
it('OAuth 2 enabled', () => {
const emulateAppIdAvailable = [
{},
{
enabled_for: [111],
},
];
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValue([emulateAppIdAvailable, true]);
const { result } = renderHook(() => useOAuth2Enabled());

expect(result.current).toStrictEqual([true]);
});

it('OAuth 2 disabled', () => {
const emulateAppIdAvailable = [
{},
{
enabled_for: [112],
},
];
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValue([emulateAppIdAvailable, true]);
const { result } = renderHook(() => useOAuth2Enabled());

expect(result.current).toStrictEqual([false]);
});
});
2 changes: 1 addition & 1 deletion src/hooks/custom-hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export { default as useLiveChat } from './useLiveChat';
export { default as useModalManager } from './useModalManager';
export { default as useNavigatorOnline } from './useNavigatorOnline';
export { default as useNetworkStatus } from './useNetworkStatus';
export { default as useOAuth } from './useOAuth';
export { default as usePoiPoaStatus } from './usePoiPoaStatus';
export { default as useQueryString } from './useQueryString';
export { default as useRedirectToOauth } from './useRedirectToOauth';
export { default as useSendbird } from './useSendbird';
export { default as useSyncedTime } from './useSyncedTime';
export { default as useTrackjs } from './useTrackjs';
3 changes: 1 addition & 2 deletions src/hooks/custom-hooks/useDerivAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ const useDerivAnalytics = () => {
const initialise = async () => {
try {
const isDerivAnalyticsInitialized = Analytics?.getInstances()?.tracking?.has_initialized;
const isLocalHost = location.hostname === 'localhost';
const isProduction = process.env.NODE_ENV === 'production';

if (!isLocalHost && !isDerivAnalyticsInitialized && websiteStatus) {
if (!isDerivAnalyticsInitialized && websiteStatus) {
const remoteConfigURL = process.env.VITE_REMOTE_CONFIG_URL;
let services = FIREBASE_INIT_DATA;
if (remoteConfigURL) {
Expand Down
20 changes: 11 additions & 9 deletions src/hooks/custom-hooks/useGrowthbookGetFeatureValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@ import { useEffect, useState } from 'react';
import { Analytics } from '@deriv-com/analytics';
import useIsGrowthbookIsLoaded from './useIsGrowthbookLoaded';

interface UseGrowthbookGetFeatureValueArgs<T> {
defaultValue?: T;
type featureValueTypes = Record<string, boolean> | boolean | string | [];

interface UseGrowthbookGetFeatureValueArgs {
defaultValue?: featureValueTypes;
featureFlag: string;
}

const useGrowthbookGetFeatureValue = <T extends boolean | string>({
const useGrowthbookGetFeatureValue = <T,>({
defaultValue,
featureFlag,
}: UseGrowthbookGetFeatureValueArgs<T>) => {
const resolvedDefaultValue: T = defaultValue !== undefined ? defaultValue : (false as T);
const [featureFlagValue, setFeatureFlagValue] = useState(
Analytics?.getFeatureValue(featureFlag, resolvedDefaultValue) ?? resolvedDefaultValue
}: UseGrowthbookGetFeatureValueArgs): [T, boolean] => {
const resolvedDefaultValue: featureValueTypes = defaultValue !== undefined ? defaultValue : false;
const [featureFlagValue, setFeatureFlagValue] = useState<T>(
(Analytics?.getFeatureValue(featureFlag, resolvedDefaultValue) ?? resolvedDefaultValue) as T
);
const isGBLoaded = useIsGrowthbookIsLoaded();

useEffect(() => {
if (isGBLoaded) {
if (Analytics?.getInstances()?.ab) {
const setFeatureValue = () => {
const value = Analytics?.getFeatureValue(featureFlag, resolvedDefaultValue);
const value = Analytics?.getFeatureValue(featureFlag, resolvedDefaultValue) as T;
setFeatureFlagValue(value);
};
setFeatureValue();
Expand All @@ -33,7 +35,7 @@ const useGrowthbookGetFeatureValue = <T extends boolean | string>({
}
}, [isGBLoaded, resolvedDefaultValue, featureFlag]);

return [featureFlagValue, isGBLoaded];
return [featureFlagValue as T, isGBLoaded];
};

export default useGrowthbookGetFeatureValue;
Loading

0 comments on commit 833fffe

Please sign in to comment.