From 0f1a50d39f86b9cf948f47c1cad1950734491e0c Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 7 May 2024 18:31:57 +0700 Subject: [PATCH 1/5] access control on iou request --- src/CONST.ts | 3 + src/components/ConnectionLayout.tsx | 4 +- src/components/SelectionScreen.tsx | 4 +- src/pages/iou/request/IOURequestStartPage.tsx | 41 ++++++-------- .../workspace/AccessOrNotFoundWrapper.tsx | 55 ++++++++++++++----- 5 files changed, 66 insertions(+), 41 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 19720c05a93c..1ffeaa754717 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1567,6 +1567,9 @@ const CONST = { ACCOUNTANT: 'accountant', }, }, + ACCESS_VARIANTS: { + CREATE: 'create', + }, }, GROWL: { diff --git a/src/components/ConnectionLayout.tsx b/src/components/ConnectionLayout.tsx index a91dea9bfc92..e6e37a3f1273 100644 --- a/src/components/ConnectionLayout.tsx +++ b/src/components/ConnectionLayout.tsx @@ -4,7 +4,7 @@ import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import type {PolicyAccessVariant} from '@pages/workspace/AccessOrNotFoundWrapper'; +import type {AccessVariant} from '@pages/workspace/AccessOrNotFoundWrapper'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {TranslationPaths} from '@src/languages/types'; import type {PolicyFeatureName} from '@src/types/onyx/Policy'; @@ -33,7 +33,7 @@ type ConnectionLayoutProps = { policyID: string; /** Defines which types of access should be verified */ - accessVariants?: PolicyAccessVariant[]; + accessVariants?: AccessVariant[]; /** The current feature name that the user tries to get access to */ featureName?: PolicyFeatureName; diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index a2ab477accef..0ff267160e07 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -1,6 +1,6 @@ import React from 'react'; import useLocalize from '@hooks/useLocalize'; -import type {PolicyAccessVariant} from '@pages/workspace/AccessOrNotFoundWrapper'; +import type {AccessVariant} from '@pages/workspace/AccessOrNotFoundWrapper'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {TranslationPaths} from '@src/languages/types'; import type {PolicyFeatureName} from '@src/types/onyx/Policy'; @@ -45,7 +45,7 @@ type SelectionScreenProps = { policyID: string; /** Defines which types of access should be verified */ - accessVariants?: PolicyAccessVariant[]; + accessVariants?: AccessVariant[]; /** The current feature name that the user tries to get access to */ featureName?: PolicyFeatureName; diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 1bbf0d02a941..3e057c4d8300 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -3,7 +3,6 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import DragAndDropProvider from '@components/DragAndDrop/Provider'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -13,13 +12,12 @@ import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; import useThemeStyles from '@hooks/useThemeStyles'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import * as IOUUtils from '@libs/IOUUtils'; import * as KeyDownPressListener from '@libs/KeyboardShortcut/KeyDownPressListener'; import Navigation from '@libs/Navigation/Navigation'; import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator'; -import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; +import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import * as IOU from '@userActions/IOU'; import type {IOURequestType} from '@userActions/IOU'; import CONST from '@src/CONST'; @@ -44,9 +42,6 @@ type IOURequestStartPageOnyxProps = { /** The transaction being modified */ transaction: OnyxEntry; - - /** The list of all policies */ - allPolicies: OnyxCollection; }; type IOURequestStartPageProps = IOURequestStartPageOnyxProps & WithWritableReportOrNotFoundProps; @@ -60,7 +55,6 @@ function IOURequestStartPage({ }, selectedTab, transaction, - allPolicies, }: IOURequestStartPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -105,9 +99,6 @@ function IOURequestStartPage({ const isExpenseReport = ReportUtils.isExpenseReport(report); const shouldDisplayDistanceRequest = (!!canUseP2PDistanceRequests || isExpenseChat || isExpenseReport || isFromGlobalCreate) && iouType !== CONST.IOU.TYPE.SPLIT; - // Allow the user to submit the expense if we are submitting the expense in global menu or the report can create the exoense - const isAllowedToCreateRequest = isEmptyObject(report?.reportID) || ReportUtils.canCreateRequest(report, policy, iouType) || PolicyUtils.canSendInvoice(allPolicies); - const navigateBack = () => { Navigation.closeRHPFlow(); }; @@ -126,15 +117,20 @@ function IOURequestStartPage({ } return ( - - {({safeAreaPaddingBottomStyle}) => ( - + + {({safeAreaPaddingBottomStyle}) => ( - - )} - + )} + + ); } @@ -180,7 +176,4 @@ export default withOnyx( transaction: { key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${route?.params.transactionID ?? 0}`, }, - allPolicies: { - key: ONYXKEYS.COLLECTION.POLICY, - }, })(IOURequestStartPage); diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index b90a9cb38151..85d63c7f423a 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -1,14 +1,17 @@ /* eslint-disable rulesdir/no-negated-variables */ import React, {useEffect} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import type {FullPageNotFoundViewProps} from '@components/BlockingViews/FullPageNotFoundView'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; +import * as ReportUtils from '@libs/ReportUtils'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as Policy from '@userActions/Policy'; +import type {IOUType} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -17,29 +20,42 @@ import type {PolicyFeatureName} from '@src/types/onyx/Policy'; import callOrReturn from '@src/types/utils/callOrReturn'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -const POLICY_ACCESS_VARIANTS = { +const ACCESS_VARIANTS = { [CONST.POLICY.ACCESS_VARIANTS.PAID]: (policy: OnyxEntry) => PolicyUtils.isPaidGroupPolicy(policy) && !!policy?.isPolicyExpenseChatEnabled, [CONST.POLICY.ACCESS_VARIANTS.ADMIN]: (policy: OnyxEntry) => PolicyUtils.isPolicyAdmin(policy), -} as const satisfies Record boolean>; + [CONST.IOU.ACCESS_VARIANTS.CREATE]: (policy: OnyxEntry, report: OnyxEntry, allPolicies: OnyxCollection, iouType?: IOUType) => + // Allow the user to submit the expense if we are submitting the expense in global menu or the report can create the expense + (isEmptyObject(report?.reportID) || ReportUtils.canCreateRequest(report, policy, iouType)) && + (iouType !== CONST.IOU.TYPE.INVOICE || PolicyUtils.canSendInvoice(allPolicies)), +} as const satisfies Record, iouType?: IOUType) => boolean>; -type PolicyAccessVariant = keyof typeof POLICY_ACCESS_VARIANTS; +type AccessVariant = keyof typeof ACCESS_VARIANTS; type AccessOrNotFoundWrapperOnyxProps = { + /** The report that holds the transaction */ + report: OnyxEntry; + /** The report currently being looked at */ policy: OnyxEntry; /** Indicated whether the report data is loading */ isLoadingReportData: OnyxEntry; + + /** The list of all policies */ + allPolicies: OnyxCollection; }; type AccessOrNotFoundWrapperProps = AccessOrNotFoundWrapperOnyxProps & { /** The children to render */ children: ((props: AccessOrNotFoundWrapperOnyxProps) => React.ReactNode) | React.ReactNode; + /** The id of the report that holds the transaction */ + reportID?: string; + /** The report currently being looked at */ - policyID: string; + policyID?: string; /** Defines which types of access should be verified */ - accessVariants?: PolicyAccessVariant[]; + accessVariants?: AccessVariant[]; /** The current feature name that the user tries to get access to */ featureName?: PolicyFeatureName; @@ -49,6 +65,9 @@ type AccessOrNotFoundWrapperProps = AccessOrNotFoundWrapperOnyxProps & { /** Whether or not to block user from accessing the page */ shouldBeBlocked?: boolean; + + /** The type of the transaction */ + iouType?: IOUType; } & Pick; type PageNotFoundFallbackProps = Pick & {shouldShowFullScreenFallback: boolean}; @@ -64,7 +83,7 @@ function PageNotFoundFallback({policyID, shouldShowFullScreenFallback, fullPageN /> ) : ( Navigation.goBack(ROUTES.WORKSPACE_PROFILE.getRoute(policyID))} + onBackButtonPress={() => !!policyID && Navigation.goBack(ROUTES.WORKSPACE_PROFILE.getRoute(policyID))} // eslint-disable-next-line react/jsx-props-no-spreading {...fullPageNotFoundViewProps} /> @@ -72,7 +91,7 @@ function PageNotFoundFallback({policyID, shouldShowFullScreenFallback, fullPageN } function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps, shouldBeBlocked, ...props}: AccessOrNotFoundWrapperProps) { - const {policy, policyID, featureName, isLoadingReportData} = props; + const {policy, policyID, report, iouType, allPolicies, featureName, isLoadingReportData} = props; const isPolicyIDInRoute = !!policyID?.length; @@ -91,12 +110,16 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps const isFeatureEnabled = featureName ? PolicyUtils.isPolicyFeatureEnabled(policy, featureName) : true; const isPageAccessible = accessVariants.reduce((acc, variant) => { - const accessFunction = POLICY_ACCESS_VARIANTS[variant]; - return acc && accessFunction(policy); + const accessFunction = ACCESS_VARIANTS[variant]; + return acc && accessFunction(policy, report, allPolicies, iouType); }, true); + const isIOU = !!iouType && IOUUtils.isValidMoneyRequestType(iouType); + const isFromGlobalCreate = isEmptyObject(report?.reportID); + + const isPolicyNotAccessible = isEmptyObject(policy) || (Object.keys(policy).length === 1 && !isEmptyObject(policy.errors)) || !policy?.id; const shouldShowNotFoundPage = - isEmptyObject(policy) || (Object.keys(policy).length === 1 && !isEmptyObject(policy.errors)) || !policy?.id || !isPageAccessible || !isFeatureEnabled || shouldBeBlocked; + isPolicyNotAccessible || !isPageAccessible || !isFeatureEnabled || shouldBeBlocked; if (shouldShowFullScreenLoadingIndicator) { return ; @@ -115,13 +138,19 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps return callOrReturn(props.children, props); } -export type {PolicyAccessVariant}; +export type {AccessVariant}; export default withOnyx({ + report: { + key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + }, policy: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID ?? ''}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, isLoadingReportData: { key: ONYXKEYS.IS_LOADING_REPORT_DATA, }, + allPolicies: { + key: ONYXKEYS.COLLECTION.POLICY, + }, })(AccessOrNotFoundWrapper); From 3a56010d6ddcd156128ff8aed45a3455c7039afc Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 8 May 2024 13:48:58 +0700 Subject: [PATCH 2/5] do not require policy for money request --- src/pages/iou/request/IOURequestStartPage.tsx | 2 +- src/pages/workspace/AccessOrNotFoundWrapper.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 3e057c4d8300..661da2c1a97a 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -1,7 +1,7 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; -import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import DragAndDropProvider from '@components/DragAndDrop/Provider'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index 85d63c7f423a..c67b4a521fe7 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -24,6 +24,8 @@ const ACCESS_VARIANTS = { [CONST.POLICY.ACCESS_VARIANTS.PAID]: (policy: OnyxEntry) => PolicyUtils.isPaidGroupPolicy(policy) && !!policy?.isPolicyExpenseChatEnabled, [CONST.POLICY.ACCESS_VARIANTS.ADMIN]: (policy: OnyxEntry) => PolicyUtils.isPolicyAdmin(policy), [CONST.IOU.ACCESS_VARIANTS.CREATE]: (policy: OnyxEntry, report: OnyxEntry, allPolicies: OnyxCollection, iouType?: IOUType) => + !!iouType && + IOUUtils.isValidMoneyRequestType(iouType) && // Allow the user to submit the expense if we are submitting the expense in global menu or the report can create the expense (isEmptyObject(report?.reportID) || ReportUtils.canCreateRequest(report, policy, iouType)) && (iouType !== CONST.IOU.TYPE.INVOICE || PolicyUtils.canSendInvoice(allPolicies)), @@ -94,6 +96,8 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps const {policy, policyID, report, iouType, allPolicies, featureName, isLoadingReportData} = props; const isPolicyIDInRoute = !!policyID?.length; + const isMoneyRequest = !!iouType && IOUUtils.isValidMoneyRequestType(iouType); + const isFromGlobalCreate = isEmptyObject(report?.reportID); useEffect(() => { if (!isPolicyIDInRoute || !isEmptyObject(policy)) { @@ -105,7 +109,7 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps // eslint-disable-next-line react-hooks/exhaustive-deps }, [isPolicyIDInRoute, policyID]); - const shouldShowFullScreenLoadingIndicator = isLoadingReportData !== false && (!Object.entries(policy ?? {}).length || !policy?.id); + const shouldShowFullScreenLoadingIndicator = !isMoneyRequest && isLoadingReportData !== false && (!Object.entries(policy ?? {}).length || !policy?.id); const isFeatureEnabled = featureName ? PolicyUtils.isPolicyFeatureEnabled(policy, featureName) : true; @@ -114,12 +118,8 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps return acc && accessFunction(policy, report, allPolicies, iouType); }, true); - const isIOU = !!iouType && IOUUtils.isValidMoneyRequestType(iouType); - const isFromGlobalCreate = isEmptyObject(report?.reportID); - const isPolicyNotAccessible = isEmptyObject(policy) || (Object.keys(policy).length === 1 && !isEmptyObject(policy.errors)) || !policy?.id; - const shouldShowNotFoundPage = - isPolicyNotAccessible || !isPageAccessible || !isFeatureEnabled || shouldBeBlocked; + const shouldShowNotFoundPage = (!isMoneyRequest && !isFromGlobalCreate && isPolicyNotAccessible) || !isPageAccessible || !isFeatureEnabled || shouldBeBlocked; if (shouldShowFullScreenLoadingIndicator) { return ; From 5c971d72dc086be81caa62186ba8557fe2ec60c6 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 8 May 2024 15:34:26 +0700 Subject: [PATCH 3/5] handle go back --- src/pages/workspace/AccessOrNotFoundWrapper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index c67b4a521fe7..c289905a1bf6 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -85,7 +85,7 @@ function PageNotFoundFallback({policyID, shouldShowFullScreenFallback, fullPageN /> ) : ( !!policyID && Navigation.goBack(ROUTES.WORKSPACE_PROFILE.getRoute(policyID))} + onBackButtonPress={() => Navigation.goBack(policyID ? ROUTES.WORKSPACE_PROFILE.getRoute(policyID) : undefined)} // eslint-disable-next-line react/jsx-props-no-spreading {...fullPageNotFoundViewProps} /> From c0ce51c4422c6a0a4ab60278d8057919220a3685 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 8 May 2024 15:38:19 +0700 Subject: [PATCH 4/5] handle go back home --- src/pages/workspace/AccessOrNotFoundWrapper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index c289905a1bf6..4740fb7f5988 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -85,7 +85,7 @@ function PageNotFoundFallback({policyID, shouldShowFullScreenFallback, fullPageN /> ) : ( Navigation.goBack(policyID ? ROUTES.WORKSPACE_PROFILE.getRoute(policyID) : undefined)} + onBackButtonPress={() => Navigation.goBack(policyID ? ROUTES.WORKSPACE_PROFILE.getRoute(policyID) : ROUTES.HOME)} // eslint-disable-next-line react/jsx-props-no-spreading {...fullPageNotFoundViewProps} /> From 5dcf980403068b7d5c243116db2caaf05807585d Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 15 May 2024 16:40:08 +0700 Subject: [PATCH 5/5] pass allPolicies from IOUStartPage --- src/pages/iou/request/IOURequestStartPage.tsx | 10 +++++++++- src/pages/workspace/AccessOrNotFoundWrapper.tsx | 11 ++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 661da2c1a97a..c1d55516b433 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -1,7 +1,7 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import DragAndDropProvider from '@components/DragAndDrop/Provider'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; @@ -42,6 +42,9 @@ type IOURequestStartPageOnyxProps = { /** The transaction being modified */ transaction: OnyxEntry; + + /** The list of all policies */ + allPolicies: OnyxCollection; }; type IOURequestStartPageProps = IOURequestStartPageOnyxProps & WithWritableReportOrNotFoundProps; @@ -55,6 +58,7 @@ function IOURequestStartPage({ }, selectedTab, transaction, + allPolicies, }: IOURequestStartPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -122,6 +126,7 @@ function IOURequestStartPage({ iouType={iouType} policyID={policy?.id} accessVariants={[CONST.IOU.ACCESS_VARIANTS.CREATE]} + allPolicies={allPolicies} > ( transaction: { key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${route?.params.transactionID ?? 0}`, }, + allPolicies: { + key: ONYXKEYS.COLLECTION.POLICY, + }, })(IOURequestStartPage); diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index 4740fb7f5988..73f0264ee308 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -41,9 +41,6 @@ type AccessOrNotFoundWrapperOnyxProps = { /** Indicated whether the report data is loading */ isLoadingReportData: OnyxEntry; - - /** The list of all policies */ - allPolicies: OnyxCollection; }; type AccessOrNotFoundWrapperProps = AccessOrNotFoundWrapperOnyxProps & { @@ -70,6 +67,9 @@ type AccessOrNotFoundWrapperProps = AccessOrNotFoundWrapperOnyxProps & { /** The type of the transaction */ iouType?: IOUType; + + /** The list of all policies */ + allPolicies?: OnyxCollection; } & Pick; type PageNotFoundFallbackProps = Pick & {shouldShowFullScreenFallback: boolean}; @@ -115,7 +115,7 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps const isPageAccessible = accessVariants.reduce((acc, variant) => { const accessFunction = ACCESS_VARIANTS[variant]; - return acc && accessFunction(policy, report, allPolicies, iouType); + return acc && accessFunction(policy, report, allPolicies ?? null, iouType); }, true); const isPolicyNotAccessible = isEmptyObject(policy) || (Object.keys(policy).length === 1 && !isEmptyObject(policy.errors)) || !policy?.id; @@ -150,7 +150,4 @@ export default withOnyx