From 043c85d2f0d284b30391eb25b9091f8c0424cec6 Mon Sep 17 00:00:00 2001 From: bobbykolev Date: Thu, 20 Feb 2025 13:42:46 +0200 Subject: [PATCH 1/3] add skip in the useRestrictedRedirect hook for awaiting the data before rerouting to restricted on VC profile and settings --- src/core/routing/useRestrictedRedirect.tsx | 9 +++++++-- .../virtualContributor/vcProfilePage/VCProfilePage.tsx | 5 ++++- .../layout/VCSettingsPageLayout.tsx | 10 +++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/core/routing/useRestrictedRedirect.tsx b/src/core/routing/useRestrictedRedirect.tsx index 330c717f7c..3068f99892 100644 --- a/src/core/routing/useRestrictedRedirect.tsx +++ b/src/core/routing/useRestrictedRedirect.tsx @@ -8,6 +8,7 @@ import { NavigateOptions } from 'react-router/lib/hooks'; interface RestrictedRedirectQueryResponse { data?: Data; error?: ApolloError; + skip?: boolean; } interface PrivilegesReader { @@ -23,7 +24,7 @@ const DEFAULT_NAVIGATE_OPTIONS: NavigateOptions = { }; const useRestrictedRedirect = ( - { data, error }: RestrictedRedirectQueryResponse, + { data, error, skip = false }: RestrictedRedirectQueryResponse, readPrivileges: PrivilegesReader, { requiredPrivilege = AuthorizationPrivilege.Read, @@ -36,6 +37,10 @@ const useRestrictedRedirect = ( const redirectUrl = `/restricted?origin=${encodeURI(pathname)}`; useEffect(() => { + if (skip) { + return; + } + if (error && isApolloForbiddenError(error)) { navigate(redirectUrl, navigateOptions); } @@ -43,7 +48,7 @@ const useRestrictedRedirect = ( if (data && !readPrivileges(data)?.includes(requiredPrivilege)) { navigate(redirectUrl, navigateOptions); } - }, [data, error]); + }, [data, error, skip]); }; export default useRestrictedRedirect; diff --git a/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx b/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx index 90ad91065f..62591bc576 100644 --- a/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx +++ b/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx @@ -47,7 +47,10 @@ export const VCProfilePage = ({ openKnowledgeBaseDialog, children }: VCProfilePa skip: !data?.lookup.virtualContributor?.aiPersona?.bodyOfKnowledgeID || !isBokSpace, }); - useRestrictedRedirect({ data, error }, data => data.lookup.virtualContributor?.authorization?.myPrivileges); + useRestrictedRedirect( + { data, error, skip: urlResolverLoading || loading }, + data => data.lookup.virtualContributor?.authorization?.myPrivileges + ); if (urlResolverLoading || loading || !vcId) { return ( diff --git a/src/domain/community/virtualContributorAdmin/layout/VCSettingsPageLayout.tsx b/src/domain/community/virtualContributorAdmin/layout/VCSettingsPageLayout.tsx index 2204c03295..1215f3226a 100644 --- a/src/domain/community/virtualContributorAdmin/layout/VCSettingsPageLayout.tsx +++ b/src/domain/community/virtualContributorAdmin/layout/VCSettingsPageLayout.tsx @@ -32,9 +32,13 @@ const VCSettingsPageLayout = ({ ...props }: PropsWithChildren const { t } = useTranslation(); - useRestrictedRedirect({ data, error }, data => data.lookup.virtualContributor?.authorization?.myPrivileges, { - requiredPrivilege: AuthorizationPrivilege.Update, - }); + useRestrictedRedirect( + { data, error, skip: urlResolverLoading || loading }, + data => data.lookup.virtualContributor?.authorization?.myPrivileges, + { + requiredPrivilege: AuthorizationPrivilege.Update, + } + ); return ( Date: Thu, 20 Feb 2025 15:00:48 +0100 Subject: [PATCH 2/3] Handle urlResolver errors on the client --- src/core/apollo/generated/apollo-helpers.ts | 4 ++++ src/core/apollo/generated/apollo-hooks.ts | 2 ++ src/core/apollo/generated/graphql-schema.ts | 5 +++++ src/main/routing/urlResolver/UrlResolverProvider.tsx | 5 +++++ src/main/routing/urlResolver/UrlResolvers.graphql | 2 ++ 5 files changed, 18 insertions(+) diff --git a/src/core/apollo/generated/apollo-helpers.ts b/src/core/apollo/generated/apollo-helpers.ts index bcd5089f57..372f7f55c6 100644 --- a/src/core/apollo/generated/apollo-helpers.ts +++ b/src/core/apollo/generated/apollo-helpers.ts @@ -3877,8 +3877,10 @@ export type UrlResolverQueryResultVirtualContributorFieldPolicy = { }; export type UrlResolverQueryResultsKeySpecifier = ( | 'discussionId' + | 'errorMessage' | 'innovationHubId' | 'innovationPack' + | 'isError' | 'organizationId' | 'space' | 'type' @@ -3888,8 +3890,10 @@ export type UrlResolverQueryResultsKeySpecifier = ( )[]; export type UrlResolverQueryResultsFieldPolicy = { discussionId?: FieldPolicy | FieldReadFunction; + errorMessage?: FieldPolicy | FieldReadFunction; innovationHubId?: FieldPolicy | FieldReadFunction; innovationPack?: FieldPolicy | FieldReadFunction; + isError?: FieldPolicy | FieldReadFunction; organizationId?: FieldPolicy | FieldReadFunction; space?: FieldPolicy | FieldReadFunction; type?: FieldPolicy | FieldReadFunction; diff --git a/src/core/apollo/generated/apollo-hooks.ts b/src/core/apollo/generated/apollo-hooks.ts index cc8673dc3f..25f95adc40 100644 --- a/src/core/apollo/generated/apollo-hooks.ts +++ b/src/core/apollo/generated/apollo-hooks.ts @@ -21788,6 +21788,8 @@ export const UrlResolverDocument = gql` } } innovationHubId + isError + errorMessage } } `; diff --git a/src/core/apollo/generated/graphql-schema.ts b/src/core/apollo/generated/graphql-schema.ts index fa52a24124..a3bd9cc551 100644 --- a/src/core/apollo/generated/graphql-schema.ts +++ b/src/core/apollo/generated/graphql-schema.ts @@ -7217,8 +7217,10 @@ export type UrlResolverQueryResultVirtualContributor = { export type UrlResolverQueryResults = { __typename?: 'UrlResolverQueryResults'; discussionId?: Maybe; + errorMessage: Scalars['String']; innovationHubId?: Maybe; innovationPack?: Maybe; + isError: Scalars['Boolean']; organizationId?: Maybe; space?: Maybe; type: UrlType; @@ -7241,6 +7243,7 @@ export enum UrlType { InnovationHub = 'INNOVATION_HUB', InnovationLibrary = 'INNOVATION_LIBRARY', InnovationPacks = 'INNOVATION_PACKS', + NotAuthorized = 'NOT_AUTHORIZED', Organization = 'ORGANIZATION', Space = 'SPACE', SpaceExplorer = 'SPACE_EXPLORER', @@ -26419,6 +26422,8 @@ export type UrlResolverQuery = { userId?: string | undefined; discussionId?: string | undefined; innovationHubId?: string | undefined; + isError: boolean; + errorMessage: string; space?: | { __typename?: 'UrlResolverQueryResultSpace'; diff --git a/src/main/routing/urlResolver/UrlResolverProvider.tsx b/src/main/routing/urlResolver/UrlResolverProvider.tsx index d8709fba56..1d0cc610b4 100644 --- a/src/main/routing/urlResolver/UrlResolverProvider.tsx +++ b/src/main/routing/urlResolver/UrlResolverProvider.tsx @@ -1,5 +1,6 @@ import { useUrlResolverQuery } from '@/core/apollo/generated/apollo-hooks'; import { SpaceLevel, UrlType } from '@/core/apollo/generated/graphql-schema'; +import { NotFoundError } from '@/core/notFound/NotFoundErrorBoundary'; import { PartialRecord } from '@/core/utils/PartialRecords'; import { compact } from 'lodash'; import { createContext, ReactNode, useEffect, useMemo, useState } from 'react'; @@ -133,6 +134,10 @@ const UrlResolverProvider = ({ children }: { children: ReactNode }) => { skip: !queryUrl, }); + if (!urlResolverLoading && urlResolverData?.urlResolver.isError) { + throw new NotFoundError(urlResolverData?.urlResolver.errorMessage); + } + const setUrlParams = (url: string) => { setQueryUrl(url); }; diff --git a/src/main/routing/urlResolver/UrlResolvers.graphql b/src/main/routing/urlResolver/UrlResolvers.graphql index a2ea4daedf..fafe664dc4 100644 --- a/src/main/routing/urlResolver/UrlResolvers.graphql +++ b/src/main/routing/urlResolver/UrlResolvers.graphql @@ -46,6 +46,8 @@ query UrlResolver($url: String!) { } } innovationHubId + isError + errorMessage } } From 44bd914a33acbfd8f1e520610bb0fbb31dc2bdd3 Mon Sep 17 00:00:00 2001 From: bobbykolev Date: Thu, 20 Feb 2025 16:17:49 +0200 Subject: [PATCH 3/3] fix no access to VC profiles from non-host members --- .../virtualContributor/vcProfilePage/VCProfilePage.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx b/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx index 62591bc576..68fec98669 100644 --- a/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx +++ b/src/domain/community/virtualContributor/vcProfilePage/VCProfilePage.tsx @@ -8,7 +8,7 @@ import { Error404 } from '@/core/pages/Errors/Error404'; import useUrlResolver from '@/main/routing/urlResolver/useUrlResolver'; import useRestrictedRedirect from '@/core/routing/useRestrictedRedirect'; import { isApolloNotFoundError } from '@/core/apollo/hooks/useApolloErrorHandler'; -import { AiPersonaBodyOfKnowledgeType } from '@/core/apollo/generated/graphql-schema'; +import { AiPersonaBodyOfKnowledgeType, AuthorizationPrivilege } from '@/core/apollo/generated/graphql-schema'; /** * children will have the virtual contributor data available if it is loaded @@ -49,7 +49,10 @@ export const VCProfilePage = ({ openKnowledgeBaseDialog, children }: VCProfilePa useRestrictedRedirect( { data, error, skip: urlResolverLoading || loading }, - data => data.lookup.virtualContributor?.authorization?.myPrivileges + data => data.lookup.virtualContributor?.authorization?.myPrivileges, + { + requiredPrivilege: AuthorizationPrivilege.ReadAbout, + } ); if (urlResolverLoading || loading || !vcId) {