Skip to content

Commit

Permalink
Fix: Include permission management on permanently delete, rename, and…
Browse files Browse the repository at this point in the history
… restore. (#62754)

Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: ellatrix <ellatrix@git.wordpress.org>
  • Loading branch information
3 people authored Jun 24, 2024
1 parent abe0925 commit 5e2050a
Showing 1 changed file with 68 additions and 26 deletions.
94 changes: 68 additions & 26 deletions packages/editor/src/components/post-actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,34 +307,29 @@ const trashPostAction = {
},
};

function useTrashPostAction( postType ) {
function useCanUserEligibilityCheckPostType( capability, resource, action ) {
const registry = useRegistry();
const { resource, cachedCanUserResolvers } = useSelect(
( select ) => {
const { getPostType, getCachedResolvers } = select( coreStore );
return {
resource: getPostType( postType )?.rest_base || '',
cachedCanUserResolvers: getCachedResolvers().canUser,
};
},
[ postType ]
);
return useMemo(
() => ( {
...trashPostAction,
...action,
isEligible( item ) {
return (
trashPostAction.isEligible( item ) &&
action.isEligible( item ) &&
registry
.select( coreStore )
.canUser( 'delete', resource, item.id )
.canUser( capability, resource, item.id )
);
},
} ),
// We are making this use memo depend on cachedCanUserResolvers as a way to make the component using this hook re-render
// when user capabilities are resolved. This makes sure the isEligible function is re-evaluated.
// eslint-disable-next-line react-hooks/exhaustive-deps
[ registry, resource, cachedCanUserResolvers ]
[ action, registry, capability, resource ]
);
}

function useTrashPostAction( resource ) {
return useCanUserEligibilityCheckPostType(
'delete',
resource,
trashPostAction
);
}

Expand Down Expand Up @@ -428,6 +423,14 @@ const permanentlyDeletePostAction = {
},
};

function usePermanentlyDeletePostAction( resource ) {
return useCanUserEligibilityCheckPostType(
'delete',
resource,
permanentlyDeletePostAction
);
}

const restorePostAction = {
id: 'restore',
label: __( 'Restore' ),
Expand Down Expand Up @@ -535,6 +538,14 @@ const restorePostAction = {
},
};

function useRestorePostAction( resource ) {
return useCanUserEligibilityCheckPostType(
'update',
resource,
restorePostAction
);
}

const viewPostAction = {
id: 'view-post',
label: __( 'View' ),
Expand Down Expand Up @@ -694,6 +705,14 @@ const renamePostAction = {
},
};

function useRenamePostAction( resource ) {
return useCanUserEligibilityCheckPostType(
'update',
resource,
renamePostAction
);
}

const useDuplicatePostAction = ( postType ) => {
const { userCanCreatePost } = useSelect(
( select ) => {
Expand Down Expand Up @@ -1038,23 +1057,36 @@ export const duplicateTemplatePartAction = {
};

export function usePostActions( { postType, onActionPerformed, context } ) {
const { defaultActions, postTypeObject, userCanCreatePostType } = useSelect(
const {
defaultActions,
postTypeObject,
userCanCreatePostType,
resource,
cachedCanUserResolvers,
} = useSelect(
( select ) => {
const { getPostType, canUser } = select( coreStore );
const { getPostType, canUser, getCachedResolvers } =
select( coreStore );
const { getEntityActions } = unlock( select( editorStore ) );
const _postTypeObject = getPostType( postType );
const resource = _postTypeObject?.rest_base || '';
const _resource = _postTypeObject?.rest_base || '';
return {
postTypeObject: _postTypeObject,
defaultActions: getEntityActions( 'postType', postType ),
userCanCreatePostType: canUser( 'create', resource ),
userCanCreatePostType: canUser( 'create', _resource ),
resource: _resource,
cachedCanUserResolvers: getCachedResolvers()?.canUser,
};
},
[ postType ]
);

const duplicatePostAction = useDuplicatePostAction( postType );
const trashPostActionForPostType = useTrashPostAction( postType );
const trashPostActionForPostType = useTrashPostAction( resource );
const permanentlyDeletePostActionForPostType =
usePermanentlyDeletePostAction( resource );
const renamePostActionForPostType = useRenamePostAction( resource );
const restorePostActionForPostType = useRestorePostAction( resource );
const isTemplateOrTemplatePart = [
TEMPLATE_POST_TYPE,
TEMPLATE_PART_POST_TYPE,
Expand All @@ -1080,13 +1112,16 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
userCanCreatePostType &&
duplicateTemplatePartAction,
isPattern && userCanCreatePostType && duplicatePatternAction,
supportsTitle && renamePostAction,
supportsTitle && renamePostActionForPostType,
isPattern && exportPatternAsJSONAction,
isTemplateOrTemplatePart ? resetTemplateAction : restorePostAction,
isTemplateOrTemplatePart
? resetTemplateAction
: restorePostActionForPostType,
isTemplateOrTemplatePart || isPattern
? deletePostAction
: trashPostActionForPostType,
! isTemplateOrTemplatePart && permanentlyDeletePostAction,
! isTemplateOrTemplatePart &&
permanentlyDeletePostActionForPostType,
...defaultActions,
].filter( Boolean );
// Filter actions based on provided context. If not provided
Expand Down Expand Up @@ -1144,6 +1179,9 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
}

return actions;
// We are making this use memo depend on cachedCanUserResolvers as a way to make the component using this hook re-render
// when user capabilities are resolved. This makes sure the isEligible functions of actions dependent on capabilities are re-evaluated.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
defaultActions,
userCanCreatePostType,
Expand All @@ -1152,10 +1190,14 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
postTypeObject?.viewable,
duplicatePostAction,
trashPostActionForPostType,
restorePostActionForPostType,
renamePostActionForPostType,
permanentlyDeletePostActionForPostType,
onActionPerformed,
isLoaded,
supportsRevisions,
supportsTitle,
context,
cachedCanUserResolvers,
] );
}

0 comments on commit 5e2050a

Please sign in to comment.