Skip to content

Commit

Permalink
feat(organizations): update page access permissions TASK-977 (#5219)
Browse files Browse the repository at this point in the history
## 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.
  • Loading branch information
jamesrkiger authored Nov 6, 2024
1 parent be9db29 commit 70a8673
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 43 deletions.
33 changes: 0 additions & 33 deletions jsapp/js/account/organizations/requireOrgOwner.component.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, {Suspense, useEffect} from 'react';
import {useNavigate} from 'react-router-dom';
import LoadingSpinner from 'js/components/common/loadingSpinner';
import {ACCOUNT_ROUTES} from 'js/account/routes.constants';
import {useOrganizationQuery} from 'js/account/stripe.api';
import {OrganizationUserRole} from '../stripe.types';

interface Props {
children: React.ReactNode;
validRoles?: OrganizationUserRole[];
mmoOnly?: boolean;
redirect?: boolean;
}

/**
* Use to handle display of pages that should only be accessible to certain user roles
* or members of MMOs. Defaults to allowing access for all users, so you must supply
* any restrictions.
*/
export const ValidateOrgPermissions = ({
children,
validRoles = undefined,
mmoOnly = false,
redirect = true,
}: Props) => {
const navigate = useNavigate();
const orgQuery = useOrganizationQuery();
const hasValidRole = validRoles ? validRoles.includes(
orgQuery.data?.request_user_role ?? OrganizationUserRole.member
) : true;
const hasValidOrg = mmoOnly ? orgQuery.data?.is_mmo : true;

// Redirect to Account Settings if conditions not met
useEffect(() => {
if (
redirect &&
orgQuery.data &&
(!hasValidRole || !hasValidOrg)
) {
navigate(ACCOUNT_ROUTES.ACCOUNT_SETTINGS);
}
}, [redirect, orgQuery.data, navigate]);

return redirect && hasValidRole && hasValidOrg ? (
<Suspense fallback={null}>{children}</Suspense>
) : (
<LoadingSpinner />
);
};
45 changes: 35 additions & 10 deletions jsapp/js/account/routes.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import {Navigate, Route} from 'react-router-dom';
import RequireAuth from 'js/router/requireAuth';
import {RequireOrgOwner} from 'js/account/organizations/requireOrgOwner.component';
import {ValidateOrgPermissions} from 'js/account/organizations/validateOrgPermissions.component';
import {OrganizationUserRole} from './stripe.types';
import {
ACCOUNT_ROUTES,
AccountSettings,
Expand Down Expand Up @@ -35,9 +36,9 @@ export default function routes() {
index
element={
<RequireAuth>
<RequireOrgOwner>
<ValidateOrgPermissions validRoles={[OrganizationUserRole.owner]}>
<PlansRoute />
</RequireOrgOwner>
</ValidateOrgPermissions>
</RequireAuth>
}
/>
Expand All @@ -46,9 +47,9 @@ export default function routes() {
index
element={
<RequireAuth>
<RequireOrgOwner>
<ValidateOrgPermissions validRoles={[OrganizationUserRole.owner]}>
<AddOnsRoute />
</RequireOrgOwner>
</ValidateOrgPermissions>
</RequireAuth>
}
/>
Expand All @@ -57,17 +58,31 @@ export default function routes() {
index
element={
<RequireAuth>
<RequireOrgOwner>
<ValidateOrgPermissions
validRoles={[
OrganizationUserRole.owner,
OrganizationUserRole.admin,
]}
>
<DataStorage activeRoute={ACCOUNT_ROUTES.USAGE} />
</RequireOrgOwner>
</ValidateOrgPermissions>
</RequireAuth>
}
/>
<Route
path={ACCOUNT_ROUTES.USAGE_PROJECT_BREAKDOWN}
element={
<RequireAuth>
<DataStorage activeRoute={ACCOUNT_ROUTES.USAGE_PROJECT_BREAKDOWN} />
<ValidateOrgPermissions
validRoles={[
OrganizationUserRole.owner,
OrganizationUserRole.admin,
]}
>
<DataStorage
activeRoute={ACCOUNT_ROUTES.USAGE_PROJECT_BREAKDOWN}
/>
</ValidateOrgPermissions>
</RequireAuth>
}
/>
Expand All @@ -93,15 +108,25 @@ export default function routes() {
path={ACCOUNT_ROUTES.ORGANIZATION_MEMBERS}
element={
<RequireAuth>
<div>Organization members view to be implemented</div>
<ValidateOrgPermissions mmoOnly>
<div>Organization members view to be implemented</div>
</ValidateOrgPermissions>
</RequireAuth>
}
/>
<Route
path={ACCOUNT_ROUTES.ORGANIZATION_SETTINGS}
element={
<RequireAuth>
<div>Organization settings view to be implemented</div>
<ValidateOrgPermissions
validRoles={[
OrganizationUserRole.owner,
OrganizationUserRole.admin,
]}
mmoOnly
>
<div>Organization settings view to be implemented</div>
</ValidateOrgPermissions>
</RequireAuth>
}
/>
Expand Down

0 comments on commit 70a8673

Please sign in to comment.