Skip to content

Commit

Permalink
Migrate canUser resolver to thunks (#34580)
Browse files Browse the repository at this point in the history
* Migrate canUser

* Lint
  • Loading branch information
adamziel authored Sep 7, 2021
1 parent 239babc commit a96a5d9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 89 deletions.
19 changes: 10 additions & 9 deletions packages/core-data/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
receiveEntityRecords,
receiveThemeSupports,
receiveEmbedPreview,
receiveUserPermission,
} from './actions';
import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities';
import { ifNotResolved, getNormalizedCommaSeparable } from './utils';
Expand Down Expand Up @@ -291,7 +290,7 @@ export function* getEmbedPreview( url ) {
* @param {string} resource REST resource to check, e.g. 'media' or 'posts'.
* @param {?string} id ID of the rest resource to check.
*/
export function* canUser( action, resource, id ) {
export const canUser = ( action, resource, id ) => async ( { dispatch } ) => {
const methods = {
create: 'POST',
read: 'GET',
Expand All @@ -308,7 +307,7 @@ export function* canUser( action, resource, id ) {

let response;
try {
response = yield apiFetch( {
response = await triggerFetch( {
path,
// Ideally this would always be an OPTIONS request, but unfortunately there's
// a bug in the REST API which causes the Allow header to not be sent on
Expand Down Expand Up @@ -336,8 +335,8 @@ export function* canUser( action, resource, id ) {

const key = compact( [ action, resource, id ] ).join( '/' );
const isAllowed = includes( allowHeader, method );
yield receiveUserPermission( key, isAllowed );
}
dispatch.receiveUserPermission( key, isAllowed );
};

/**
* Checks whether the current user can perform the given action on the given
Expand All @@ -347,16 +346,18 @@ export function* canUser( action, resource, id ) {
* @param {string} name Entity name.
* @param {string} recordId Record's id.
*/
export function* canUserEditEntityRecord( kind, name, recordId ) {
const entities = yield getKindEntities( kind );
export const canUserEditEntityRecord = ( kind, name, recordId ) => async ( {
dispatch,
} ) => {
const entities = await dispatch( getKindEntities( kind ) );
const entity = find( entities, { kind, name } );
if ( ! entity ) {
return;
}

const resource = entity.__unstable_rest_base;
yield canUser( 'update', resource, recordId );
}
await dispatch( canUser( 'update', resource, recordId ) );
};

/**
* Request autosave data from the REST API.
Expand Down
152 changes: 72 additions & 80 deletions packages/core-data/src/test/resolvers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* WordPress dependencies
*/
import { apiFetch } from '@wordpress/data-controls';
import triggerFetch from '@wordpress/api-fetch';

jest.mock( '@wordpress/api-fetch' );
Expand All @@ -17,11 +16,7 @@ import {
getAutosaves,
getCurrentUser,
} from '../resolvers';
import {
receiveEmbedPreview,
receiveUserPermission,
receiveCurrentUser,
} from '../actions';
import { receiveEmbedPreview, receiveCurrentUser } from '../actions';

describe( 'getEntityRecord', () => {
const POST_TYPE = { slug: 'post' };
Expand Down Expand Up @@ -279,106 +274,103 @@ describe( 'getEmbedPreview', () => {
} );

describe( 'canUser', () => {
it( 'does nothing when there is an API error', () => {
const generator = canUser( 'create', 'media' );

let received = generator.next();
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
apiFetch( {
path: '/wp/v2/media',
method: 'OPTIONS',
parse: false,
} )
beforeEach( async () => {
triggerFetch.mockReset();
} );

it( 'does nothing when there is an API error', async () => {
const dispatch = Object.assign( jest.fn(), {
receiveUserPermission: jest.fn(),
} );

triggerFetch.mockImplementation( () =>
Promise.reject( { status: 404 } )
);

received = generator.throw( { status: 404 } );
expect( received.done ).toBe( true );
expect( received.value ).toBeUndefined();
await canUser( 'create', 'media' )( { dispatch } );

expect( triggerFetch ).toHaveBeenCalledWith( {
path: '/wp/v2/media',
method: 'OPTIONS',
parse: false,
} );

expect( dispatch.receiveUserPermission ).not.toHaveBeenCalled();
} );

it( 'receives false when the user is not allowed to perform an action', () => {
const generator = canUser( 'create', 'media' );

let received = generator.next();
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
apiFetch( {
path: '/wp/v2/media',
method: 'OPTIONS',
parse: false,
} )
);
it( 'receives false when the user is not allowed to perform an action', async () => {
const dispatch = Object.assign( jest.fn(), {
receiveUserPermission: jest.fn(),
} );

received = generator.next( {
triggerFetch.mockImplementation( () => ( {
headers: {
Allow: 'GET',
},
} ) );

await canUser( 'create', 'media' )( { dispatch } );

expect( triggerFetch ).toHaveBeenCalledWith( {
path: '/wp/v2/media',
method: 'OPTIONS',
parse: false,
} );
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
receiveUserPermission( 'create/media', false )
);

received = generator.next();
expect( received.done ).toBe( true );
expect( received.value ).toBeUndefined();
expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith(
'create/media',
false
);
} );

it( 'receives true when the user is allowed to perform an action', () => {
const generator = canUser( 'create', 'media' );

let received = generator.next();
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
apiFetch( {
path: '/wp/v2/media',
method: 'OPTIONS',
parse: false,
} )
);
it( 'receives true when the user is allowed to perform an action', async () => {
const dispatch = Object.assign( jest.fn(), {
receiveUserPermission: jest.fn(),
} );

received = generator.next( {
triggerFetch.mockImplementation( () => ( {
headers: {
Allow: 'POST, GET, PUT, DELETE',
},
} ) );

await canUser( 'create', 'media' )( { dispatch } );

expect( triggerFetch ).toHaveBeenCalledWith( {
path: '/wp/v2/media',
method: 'OPTIONS',
parse: false,
} );
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
receiveUserPermission( 'create/media', true )
);

received = generator.next();
expect( received.done ).toBe( true );
expect( received.value ).toBeUndefined();
expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith(
'create/media',
true
);
} );

it( 'receives true when the user is allowed to perform an action on a specific resource', () => {
const generator = canUser( 'update', 'blocks', 123 );

let received = generator.next();
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
apiFetch( {
path: '/wp/v2/blocks/123',
method: 'GET',
parse: false,
} )
);
it( 'receives true when the user is allowed to perform an action on a specific resource', async () => {
const dispatch = Object.assign( jest.fn(), {
receiveUserPermission: jest.fn(),
} );

received = generator.next( {
triggerFetch.mockImplementation( () => ( {
headers: {
Allow: 'POST, GET, PUT, DELETE',
},
} ) );

await canUser( 'create', 'blocks', 123 )( { dispatch } );

expect( triggerFetch ).toHaveBeenCalledWith( {
path: '/wp/v2/blocks/123',
method: 'GET',
parse: false,
} );
expect( received.done ).toBe( false );
expect( received.value ).toEqual(
receiveUserPermission( 'update/blocks/123', true )
);

received = generator.next();
expect( received.done ).toBe( true );
expect( received.value ).toBeUndefined();
expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith(
'create/blocks/123',
true
);
} );
} );

Expand Down

0 comments on commit a96a5d9

Please sign in to comment.