Skip to content

Commit b3a3dbc

Browse files
MelvinBotmadmax330
andcommitted
Allow policy admins to assign cards on shared workspaces via linkedPolicyIDs
The permission check in useIsAllowedToIssueCompanyCard only allowed card assignment when the feed's domainID matched the current workspace's workspaceAccountID. For feeds shared to other workspaces via linkedPolicyIDs, this check failed, causing the assign button to be greyed out even for workspace admins. This adds a linkedPolicyIDs check so policy admins on any linked workspace can assign cards. Co-authored-by: Maxence Coulibaly <madmax330@users.noreply.github.com>
1 parent 0299f56 commit b3a3dbc

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

src/hooks/useIsAllowedToIssueCompanyCard.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function useIsAllowedToIssueCompanyCard({policyID}: {policyID?: string}) {
2020
const selectedFeedData = selectedFeed && companyCards[selectedFeed];
2121
const [domain] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${selectedFeedData?.domainID}`);
2222

23-
if (selectedFeedData?.domainID === policy?.workspaceAccountID) {
23+
if (selectedFeedData?.domainID === policy?.workspaceAccountID || selectedFeedData?.linkedPolicyIDs?.includes(policyID ?? '')) {
2424
return isPolicyAdmin;
2525
}
2626

tests/unit/hooks/useIsAllowedToIssueCompanyCard.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ const workspaceAccountID = 11111111;
1414

1515
const mockPolicy = {...createRandomPolicy(Number(mockPolicyID), CONST.POLICY.TYPE.TEAM, 'TestPolicy'), policyID: mockPolicyID, workspaceAccountID};
1616

17+
const linkedFeedDomainID = 22222222;
18+
1719
const mockedFeeds = {
1820
// eslint-disable-next-line @typescript-eslint/naming-convention
1921
'vcf#19475968': {
@@ -31,6 +33,15 @@ const mockedFeeds = {
3133
customFeedName: 'Custom feed name 1',
3234
feed: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA,
3335
},
36+
// eslint-disable-next-line @typescript-eslint/naming-convention
37+
'vcf#22222222': {
38+
liabilityType: 'personal',
39+
pending: false,
40+
domainID: linkedFeedDomainID,
41+
customFeedName: 'Linked feed',
42+
feed: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA,
43+
linkedPolicyIDs: [mockPolicyID],
44+
},
3445
};
3546

3647
jest.mock('@hooks/useCardFeeds', () => ({
@@ -92,4 +103,22 @@ describe('useIsAllowedToIssueCompanyCard', () => {
92103
const {result} = renderHook(() => useIsAllowedToIssueCompanyCard({policyID: mockPolicyID}));
93104
expect(result?.current).toBe(false);
94105
});
106+
it('should return true if feed is shared via linkedPolicyIDs and user is admin', async () => {
107+
await Onyx.merge(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${mockPolicy?.policyID}`, 'vcf#22222222');
108+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${mockPolicy?.policyID}`, {
109+
role: CONST.POLICY.ROLE.ADMIN,
110+
});
111+
(useCardFeeds as jest.Mock).mockReturnValue([mockedFeeds, {status: 'loaded'}]);
112+
const {result} = renderHook(() => useIsAllowedToIssueCompanyCard({policyID: mockPolicyID}));
113+
expect(result?.current).toBe(true);
114+
});
115+
it('should return false if feed is shared via linkedPolicyIDs and user is not an admin', async () => {
116+
await Onyx.merge(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${mockPolicy?.policyID}`, 'vcf#22222222');
117+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${mockPolicy?.policyID}`, {
118+
role: CONST.POLICY.ROLE.USER,
119+
});
120+
(useCardFeeds as jest.Mock).mockReturnValue([mockedFeeds, {status: 'loaded'}]);
121+
const {result} = renderHook(() => useIsAllowedToIssueCompanyCard({policyID: mockPolicyID}));
122+
expect(result?.current).toBe(false);
123+
});
95124
});

0 commit comments

Comments
 (0)