From ec29880e3ebbb2fe4727d7f633c8219c58372288 Mon Sep 17 00:00:00 2001 From: RJ <27843274+rjchow@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:53:52 +1000 Subject: [PATCH] fix: added pre-API call permissions check on APIs being called on non-admin accessible screens (#51406) fix: no permissions api errors --- .../changelog/fix-no-permissions-api-error | 4 ++++ packages/js/data/src/notes/resolvers.ts | 3 +++ packages/js/data/src/onboarding/resolvers.ts | 3 +++ packages/js/data/src/plugins/resolvers.ts | 7 ++++++ packages/js/data/src/utils.ts | 22 +++++++++++++++++-- .../client/activity-panel/activity-panel.js | 3 ++- .../changelog/fix-no-permissions-api-error | 4 ++++ 7 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 packages/js/data/changelog/fix-no-permissions-api-error create mode 100644 plugins/woocommerce/changelog/fix-no-permissions-api-error diff --git a/packages/js/data/changelog/fix-no-permissions-api-error b/packages/js/data/changelog/fix-no-permissions-api-error new file mode 100644 index 00000000000..0695a289f9a --- /dev/null +++ b/packages/js/data/changelog/fix-no-permissions-api-error @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Added pre-API call permission checks for some API calls that were being called on non-admin accessible screens diff --git a/packages/js/data/src/notes/resolvers.ts b/packages/js/data/src/notes/resolvers.ts index 5a0dec47e6e..1da6d7d9845 100644 --- a/packages/js/data/src/notes/resolvers.ts +++ b/packages/js/data/src/notes/resolvers.ts @@ -10,11 +10,14 @@ import { apiFetch } from '@wordpress/data-controls'; import { NAMESPACE } from '../constants'; import { setNotes, setNotesQuery, setError } from './actions'; import { NoteQuery, Note } from './types'; +import { checkUserCapability } from '../utils'; export function* getNotes( query: NoteQuery = {} ) { const url = addQueryArgs( `${ NAMESPACE }/admin/notes`, query ); try { + yield checkUserCapability( 'manage_woocommerce' ); + const notes: Note[] = yield apiFetch( { path: url, } ); diff --git a/packages/js/data/src/onboarding/resolvers.ts b/packages/js/data/src/onboarding/resolvers.ts index a74e7be4760..814094413b7 100644 --- a/packages/js/data/src/onboarding/resolvers.ts +++ b/packages/js/data/src/onboarding/resolvers.ts @@ -31,6 +31,7 @@ import { TaskListType, } from './types'; import { Plugin } from '../plugins/types'; +import { checkUserCapability } from '../utils'; const resolveSelect = controls && controls.resolveSelect ? controls.resolveSelect : select; @@ -68,6 +69,8 @@ export function* getEmailPrefill() { export function* getTaskLists() { const deprecatedTasks = new DeprecatedTasks(); try { + yield checkUserCapability( 'manage_woocommerce' ); + const results: TaskListType[] = yield apiFetch( { path: WC_ADMIN_NAMESPACE + '/onboarding/tasks', method: deprecatedTasks.hasDeprecatedTasks() ? 'POST' : 'GET', diff --git a/packages/js/data/src/plugins/resolvers.ts b/packages/js/data/src/plugins/resolvers.ts index f656099ed95..c25fdfeeea5 100644 --- a/packages/js/data/src/plugins/resolvers.ts +++ b/packages/js/data/src/plugins/resolvers.ts @@ -27,6 +27,7 @@ import { RecommendedTypes, JetpackConnectionDataResponse, } from './types'; +import { checkUserCapability } from '../utils'; // Can be removed in WP 5.9, wp.data is supported in >5.7. const resolveSelect = @@ -61,6 +62,8 @@ type ConnectJetpackResponse = { export function* getActivePlugins() { yield setIsRequesting( 'getActivePlugins', true ); try { + yield checkUserCapability( 'manage_woocommerce' ); + const url = WC_ADMIN_NAMESPACE + '/plugins/active'; const results: PluginGetResponse = yield apiFetch( { path: url, @@ -77,6 +80,8 @@ export function* getInstalledPlugins() { yield setIsRequesting( 'getInstalledPlugins', true ); try { + yield checkUserCapability( 'manage_woocommerce' ); + const url = WC_ADMIN_NAMESPACE + '/plugins/installed'; const results: PluginGetResponse = yield apiFetch( { path: url, @@ -111,6 +116,8 @@ export function* getJetpackConnectionData() { yield setIsRequesting( 'getJetpackConnectionData', true ); try { + yield checkUserCapability( 'manage_woocommerce' ); + const url = JETPACK_NAMESPACE + '/connection/data'; const results: JetpackConnectionDataResponse = yield apiFetch( { diff --git a/packages/js/data/src/utils.ts b/packages/js/data/src/utils.ts index eff7bf1a483..1c0b80b7792 100644 --- a/packages/js/data/src/utils.ts +++ b/packages/js/data/src/utils.ts @@ -2,14 +2,15 @@ * External dependencies */ import { addQueryArgs } from '@wordpress/url'; -import { apiFetch } from '@wordpress/data-controls'; +import { apiFetch, select } from '@wordpress/data-controls'; /** * Internal dependencies */ import { BaseQueryParams } from './types/query-params'; import { fetchWithHeaders } from './controls'; - +import { USER_STORE_NAME } from './user'; +import { WCUser } from './user/types'; function replacer( _: string, value: unknown ) { if ( value ) { if ( Array.isArray( value ) ) { @@ -100,3 +101,20 @@ export function* request< Query extends BaseQueryParams, DataType >( return { items: response.data, totalCount }; } } + +/** + * Utility function to check if the current user has a specific capability. + * + * @param {string} capability - The capability to check (e.g. 'manage_woocommerce'). + * @throws {Error} If the user does not have the required capability. + */ +export function* checkUserCapability( capability: string ) { + const currentUser: WCUser< 'capabilities' > = yield select( + USER_STORE_NAME, + 'getCurrentUser' + ); + + if ( ! currentUser.capabilities[ capability ] ) { + throw new Error( `User does not have ${ capability } capability.` ); + } +} diff --git a/plugins/woocommerce-admin/client/activity-panel/activity-panel.js b/plugins/woocommerce-admin/client/activity-panel/activity-panel.js index 65fb6d08588..47373cf8e88 100644 --- a/plugins/woocommerce-admin/client/activity-panel/activity-panel.js +++ b/plugins/woocommerce-admin/client/activity-panel/activity-panel.js @@ -269,7 +269,8 @@ export const ActivityPanel = ( { isEmbedded, query } ) => { visible: ( isEmbedded || ! isHomescreen ) && ! isPerformingSetupTask() && - ! isProductScreen(), + ! isProductScreen() && + currentUserCan( 'manage_woocommerce' ), }; const feedback = { diff --git a/plugins/woocommerce/changelog/fix-no-permissions-api-error b/plugins/woocommerce/changelog/fix-no-permissions-api-error new file mode 100644 index 00000000000..0695a289f9a --- /dev/null +++ b/plugins/woocommerce/changelog/fix-no-permissions-api-error @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Added pre-API call permission checks for some API calls that were being called on non-admin accessible screens