From e1505b2a202f05ac49c6341cfc39eef5698cfd02 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 30 Aug 2022 10:45:31 +0200 Subject: [PATCH] chore: supporting the `PermissionedRoute` in `rr-beta` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: blam --- .../react-router-stable-migration.md | 2 + .../core-app-api/src/routing/FlatRoutes.tsx | 10 ++-- .../src/components/PermissionedRoute.tsx | 50 ++++++++++++++----- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/docs/tutorials/react-router-stable-migration.md b/docs/tutorials/react-router-stable-migration.md index bf6f26577b..441d9964a9 100644 --- a/docs/tutorials/react-router-stable-migration.md +++ b/docs/tutorials/react-router-stable-migration.md @@ -155,6 +155,8 @@ rendered instead, but it will now throw an error. Because of the above change, the `PermissionedRoute` component no longer works in all situations with React Router v6 stable. It has been deprecated in favor of the new `RequirePermission` component, which can be placed anywhere in order to perform a permissions check. +It's crucial that you update to `RequirePermission` at the same time as you update to React Router v6 stable as the `PermissionedRoute` component will no longer function. + ```diff - { const app = useApp(); const { NotFoundErrorPage } = app.getComponents(); + const isBeta = useMemo(() => isReactRouterBeta(), []); const routes = useElementFilter(props.children, elements => elements .getElements<{ @@ -65,14 +67,14 @@ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => { } path = path?.replace(/\/\*$/, '') ?? '/'; - let element = child.props.element; - if (!element) { + let element = isBeta ? child : child.props.element; + if (!isBeta && !element) { element = child; if (!warned && process.env.NODE_ENV !== 'test') { // eslint-disable-next-line no-console console.warn( 'DEPRECATION WARNING: All elements within must be of type with an element prop. ' + - 'Existing usages of should be replaced with } />', + 'Existing usages of should be replaced with } />.', ); warned = true; } diff --git a/plugins/permission-react/src/components/PermissionedRoute.tsx b/plugins/permission-react/src/components/PermissionedRoute.tsx index 4a0046c61a..2e2345a3dc 100644 --- a/plugins/permission-react/src/components/PermissionedRoute.tsx +++ b/plugins/permission-react/src/components/PermissionedRoute.tsx @@ -14,9 +14,12 @@ * limitations under the License. */ -import { ComponentProps, ReactElement } from 'react'; +import React, { ComponentProps, ReactElement, ReactNode } from 'react'; import { Route } from 'react-router'; +import { useApp } from '@backstage/core-plugin-api'; +import { usePermission } from '../hooks'; import { + isResourcePermission, Permission, ResourcePermission, } from '@backstage/plugin-permission-common'; @@ -29,20 +32,41 @@ import { * @deprecated This component no longer works with the most recent version of `@backstage/core-app-api` and react-router v6, use {@link RequirePermission} instead. */ export const PermissionedRoute = ( - _props: ComponentProps & { + props: { + caseSensitive?: boolean; + children?: ReactNode; + element?: ReactElement | null; + path?: string; errorComponent?: ReactElement | null; } & ( - | { - permission: Exclude; - resourceRef?: never; - } - | { - permission: ResourcePermission; - resourceRef: string | undefined; - } - ), + | { + permission: Exclude; + resourceRef?: never; + } + | { + permission: ResourcePermission; + resourceRef: string | undefined; + } + ), ) => { - throw new Error( - 'PermissionedRoute is no longer supported, switch to using instead: ...}/>', + const { permission, resourceRef, errorComponent, ...otherProps } = props; + + const permissionResult = usePermission( + isResourcePermission(permission) + ? { permission, resourceRef } + : { permission }, ); + const app = useApp(); + const { NotFoundErrorPage } = app.getComponents(); + + let shownElement: ReactElement | null | undefined = + errorComponent === undefined ? : errorComponent; + + if (permissionResult.loading) { + shownElement = null; + } else if (permissionResult.allowed) { + shownElement = props.element; + } + + return ; };