Skip to content

Commit 70a8673

Browse files
authored
feat(organizations): update page access permissions TASK-977 (#5219)
## Description For various pages in account settings, we previously used a wrapper component to verify whether the user was the owner of their org before allowing them to access the page. With the organizations project, this permissions check needs to allow for checking multiple role options. We also need to be able to check whether an org is an mmo for the members page. This PR overhauls the old wrapper component to allow for these checks.
1 parent be9db29 commit 70a8673

File tree

3 files changed

+84
-43
lines changed

3 files changed

+84
-43
lines changed

jsapp/js/account/organizations/requireOrgOwner.component.tsx

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React, {Suspense, useEffect} from 'react';
2+
import {useNavigate} from 'react-router-dom';
3+
import LoadingSpinner from 'js/components/common/loadingSpinner';
4+
import {ACCOUNT_ROUTES} from 'js/account/routes.constants';
5+
import {useOrganizationQuery} from 'js/account/stripe.api';
6+
import {OrganizationUserRole} from '../stripe.types';
7+
8+
interface Props {
9+
children: React.ReactNode;
10+
validRoles?: OrganizationUserRole[];
11+
mmoOnly?: boolean;
12+
redirect?: boolean;
13+
}
14+
15+
/**
16+
* Use to handle display of pages that should only be accessible to certain user roles
17+
* or members of MMOs. Defaults to allowing access for all users, so you must supply
18+
* any restrictions.
19+
*/
20+
export const ValidateOrgPermissions = ({
21+
children,
22+
validRoles = undefined,
23+
mmoOnly = false,
24+
redirect = true,
25+
}: Props) => {
26+
const navigate = useNavigate();
27+
const orgQuery = useOrganizationQuery();
28+
const hasValidRole = validRoles ? validRoles.includes(
29+
orgQuery.data?.request_user_role ?? OrganizationUserRole.member
30+
) : true;
31+
const hasValidOrg = mmoOnly ? orgQuery.data?.is_mmo : true;
32+
33+
// Redirect to Account Settings if conditions not met
34+
useEffect(() => {
35+
if (
36+
redirect &&
37+
orgQuery.data &&
38+
(!hasValidRole || !hasValidOrg)
39+
) {
40+
navigate(ACCOUNT_ROUTES.ACCOUNT_SETTINGS);
41+
}
42+
}, [redirect, orgQuery.data, navigate]);
43+
44+
return redirect && hasValidRole && hasValidOrg ? (
45+
<Suspense fallback={null}>{children}</Suspense>
46+
) : (
47+
<LoadingSpinner />
48+
);
49+
};

jsapp/js/account/routes.tsx

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React from 'react';
22
import {Navigate, Route} from 'react-router-dom';
33
import RequireAuth from 'js/router/requireAuth';
4-
import {RequireOrgOwner} from 'js/account/organizations/requireOrgOwner.component';
4+
import {ValidateOrgPermissions} from 'js/account/organizations/validateOrgPermissions.component';
5+
import {OrganizationUserRole} from './stripe.types';
56
import {
67
ACCOUNT_ROUTES,
78
AccountSettings,
@@ -35,9 +36,9 @@ export default function routes() {
3536
index
3637
element={
3738
<RequireAuth>
38-
<RequireOrgOwner>
39+
<ValidateOrgPermissions validRoles={[OrganizationUserRole.owner]}>
3940
<PlansRoute />
40-
</RequireOrgOwner>
41+
</ValidateOrgPermissions>
4142
</RequireAuth>
4243
}
4344
/>
@@ -46,9 +47,9 @@ export default function routes() {
4647
index
4748
element={
4849
<RequireAuth>
49-
<RequireOrgOwner>
50+
<ValidateOrgPermissions validRoles={[OrganizationUserRole.owner]}>
5051
<AddOnsRoute />
51-
</RequireOrgOwner>
52+
</ValidateOrgPermissions>
5253
</RequireAuth>
5354
}
5455
/>
@@ -57,17 +58,31 @@ export default function routes() {
5758
index
5859
element={
5960
<RequireAuth>
60-
<RequireOrgOwner>
61+
<ValidateOrgPermissions
62+
validRoles={[
63+
OrganizationUserRole.owner,
64+
OrganizationUserRole.admin,
65+
]}
66+
>
6167
<DataStorage activeRoute={ACCOUNT_ROUTES.USAGE} />
62-
</RequireOrgOwner>
68+
</ValidateOrgPermissions>
6369
</RequireAuth>
6470
}
6571
/>
6672
<Route
6773
path={ACCOUNT_ROUTES.USAGE_PROJECT_BREAKDOWN}
6874
element={
6975
<RequireAuth>
70-
<DataStorage activeRoute={ACCOUNT_ROUTES.USAGE_PROJECT_BREAKDOWN} />
76+
<ValidateOrgPermissions
77+
validRoles={[
78+
OrganizationUserRole.owner,
79+
OrganizationUserRole.admin,
80+
]}
81+
>
82+
<DataStorage
83+
activeRoute={ACCOUNT_ROUTES.USAGE_PROJECT_BREAKDOWN}
84+
/>
85+
</ValidateOrgPermissions>
7186
</RequireAuth>
7287
}
7388
/>
@@ -93,15 +108,25 @@ export default function routes() {
93108
path={ACCOUNT_ROUTES.ORGANIZATION_MEMBERS}
94109
element={
95110
<RequireAuth>
96-
<div>Organization members view to be implemented</div>
111+
<ValidateOrgPermissions mmoOnly>
112+
<div>Organization members view to be implemented</div>
113+
</ValidateOrgPermissions>
97114
</RequireAuth>
98115
}
99116
/>
100117
<Route
101118
path={ACCOUNT_ROUTES.ORGANIZATION_SETTINGS}
102119
element={
103120
<RequireAuth>
104-
<div>Organization settings view to be implemented</div>
121+
<ValidateOrgPermissions
122+
validRoles={[
123+
OrganizationUserRole.owner,
124+
OrganizationUserRole.admin,
125+
]}
126+
mmoOnly
127+
>
128+
<div>Organization settings view to be implemented</div>
129+
</ValidateOrgPermissions>
105130
</RequireAuth>
106131
}
107132
/>

0 commit comments

Comments
 (0)