Skip to content

Commit

Permalink
fix(reference): infinite loop on permisson check for cross space refe…
Browse files Browse the repository at this point in the history
…rences []
  • Loading branch information
chrishelgert committed Jan 15, 2025
1 parent 4ab2348 commit 462bdfc
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 18 deletions.
37 changes: 23 additions & 14 deletions packages/reference/src/common/useContentTypePermissions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useEffect, useMemo, useState } from 'react';

import { isEqual } from 'lodash';

import { ContentType, ContentEntityType, FieldAppSDK } from '../types';
import { ReferenceValidations } from '../utils/fromFieldValidations';
import { ReferenceEditorProps } from './ReferenceEditor';
Expand Down Expand Up @@ -28,24 +30,26 @@ async function filter<T, S extends T>(arr: T[], predicate: (value: T) => Promise
return results.filter((x) => x !== fail) as S[];
}

export function useContentTypePermissions(
props: ContentTypePermissionsProps
): ContentTypePermissions {
export function useContentTypePermissions({
entityType,
validations,
sdk,
allContentTypes,
}: ContentTypePermissionsProps): ContentTypePermissions {
const availableContentTypes = useMemo(() => {
if (props.entityType === 'Asset') {
if (entityType === 'Asset') {
return [];
}

if (props.validations.contentTypes) {
return props.allContentTypes.filter((ct) =>
props.validations.contentTypes?.includes(ct.sys.id)
);
if (validations.contentTypes) {
return allContentTypes.filter((ct) => validations.contentTypes?.includes(ct.sys.id));
}

return props.allContentTypes;
}, [props.allContentTypes, props.validations.contentTypes, props.entityType]);
return allContentTypes;
}, [allContentTypes, validations.contentTypes, entityType]);

const [creatableContentTypes, setCreatableContentTypes] = useState(availableContentTypes);
const { canPerformActionOnEntryOfType } = useAccessApi(props.sdk.access);
const { canPerformActionOnEntryOfType } = useAccessApi(sdk.access);

useEffect(() => {
function getContentTypes(action: 'create' | 'read') {
Expand All @@ -56,12 +60,17 @@ export function useContentTypePermissions(

async function checkContentTypeAccess() {
const creatable = await getContentTypes('create');
setCreatableContentTypes(creatable);
// Important as `filter` creates a new array and otherwise always a "new value" would be written to the state
if (!isEqual(creatable, creatableContentTypes)) {
setCreatableContentTypes(creatable);
}
}

void checkContentTypeAccess();
if (availableContentTypes.length > 0) {
void checkContentTypeAccess();
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies
}, [availableContentTypes]);
}, [availableContentTypes, creatableContentTypes]);

return {
creatableContentTypes,
Expand Down
15 changes: 11 additions & 4 deletions packages/reference/src/common/useEditorPermissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@ export type EditorPermissionsProps = {
allContentTypes: ContentType[];
};

export function useEditorPermissions(props: EditorPermissionsProps) {
const { sdk, entityType, parameters } = props;
const validations = useMemo(() => fromFieldValidations(props.sdk.field), [props.sdk.field]);
export function useEditorPermissions({
sdk,
entityType,
parameters,
allContentTypes,
}: EditorPermissionsProps) {
const validations = useMemo(() => fromFieldValidations(sdk.field), [sdk.field]);
const [canCreateEntity, setCanCreateEntity] = useState(true);
const [canLinkEntity, setCanLinkEntity] = useState(true);
const { creatableContentTypes, availableContentTypes } = useContentTypePermissions({
...props,
entityType,
validations,
sdk,
allContentTypes,
parameters,
});
const { canPerformAction } = useAccessApi(sdk.access);

Expand Down

0 comments on commit 462bdfc

Please sign in to comment.