-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Core Data: Resolve user capabilities when fetching an entity #63430
Changes from all commits
a726f88
b2a0f40
3ca0afa
a9b931e
23ea0c1
c8ae4b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,13 @@ import apiFetch from '@wordpress/api-fetch'; | |
*/ | ||
import { STORE_NAME } from './name'; | ||
import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities'; | ||
import { forwardResolver, getNormalizedCommaSeparable } from './utils'; | ||
import { | ||
forwardResolver, | ||
getNormalizedCommaSeparable, | ||
getUserPermissionCacheKey, | ||
getUserPermissionsFromResponse, | ||
ALLOWED_RESOURCE_ACTIONS, | ||
} from './utils'; | ||
import { getSyncProvider } from './sync'; | ||
import { fetchBlockPatterns } from './fetch'; | ||
|
||
|
@@ -58,7 +64,7 @@ export const getCurrentUser = | |
*/ | ||
export const getEntityRecord = | ||
( kind, name, key = '', query ) => | ||
async ( { select, dispatch } ) => { | ||
async ( { select, dispatch, registry } ) => { | ||
const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); | ||
const entityConfig = configs.find( | ||
( config ) => config.name === name && config.kind === kind | ||
|
@@ -165,8 +171,29 @@ export const getEntityRecord = | |
} | ||
} | ||
|
||
const record = await apiFetch( { path } ); | ||
dispatch.receiveEntityRecords( kind, name, record, query ); | ||
const response = await apiFetch( { path, parse: false } ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Setting
getEntityRecord( 'postType', 'post', '', { per_page: -1 } ); This will fetch the entire collection anyway, won't it? And should trigger There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also had similar concerns during the original discussion: #43480 (comment). But it shouldn't affect the The Calling |
||
const record = await response.json(); | ||
const permissions = getUserPermissionsFromResponse( response ); | ||
|
||
registry.batch( () => { | ||
dispatch.receiveEntityRecords( kind, name, record, query ); | ||
|
||
for ( const action of ALLOWED_RESOURCE_ACTIONS ) { | ||
const permissionKey = getUserPermissionCacheKey( | ||
action, | ||
{ kind, name, id: key } | ||
); | ||
|
||
dispatch.receiveUserPermission( | ||
Mamaduka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
permissionKey, | ||
permissions[ action ] | ||
); | ||
dispatch.finishResolution( 'canUser', [ | ||
action, | ||
{ kind, name, id: key }, | ||
] ); | ||
} | ||
} ); | ||
} | ||
} finally { | ||
dispatch.__unstableReleaseStoreLock( lock ); | ||
|
@@ -355,9 +382,7 @@ export const getEmbedPreview = | |
export const canUser = | ||
( requestedAction, resource, id ) => | ||
async ( { dispatch, registry } ) => { | ||
const retrievedActions = [ 'create', 'read', 'update', 'delete' ]; | ||
|
||
if ( ! retrievedActions.includes( requestedAction ) ) { | ||
if ( ! ALLOWED_RESOURCE_ACTIONS.includes( requestedAction ) ) { | ||
throw new Error( `'${ requestedAction }' is not a valid action.` ); | ||
} | ||
|
||
|
@@ -389,7 +414,7 @@ export const canUser = | |
const { hasStartedResolution } = registry.select( STORE_NAME ); | ||
|
||
// Prevent resolving the same resource twice. | ||
for ( const relatedAction of retrievedActions ) { | ||
for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) { | ||
if ( relatedAction === requestedAction ) { | ||
continue; | ||
} | ||
|
@@ -416,31 +441,10 @@ export const canUser = | |
return; | ||
} | ||
|
||
// Optional chaining operator is used here because the API requests don't | ||
// return the expected result in the native version. Instead, API requests | ||
// only return the result, without including response properties like the headers. | ||
const allowedMethods = response.headers?.get( 'allow' ) || ''; | ||
|
||
const permissions = {}; | ||
const methods = { | ||
create: 'POST', | ||
read: 'GET', | ||
update: 'PUT', | ||
delete: 'DELETE', | ||
}; | ||
for ( const [ actionName, methodName ] of Object.entries( methods ) ) { | ||
permissions[ actionName ] = allowedMethods.includes( methodName ); | ||
} | ||
|
||
const permissions = getUserPermissionsFromResponse( response ); | ||
registry.batch( () => { | ||
for ( const action of retrievedActions ) { | ||
const key = ( | ||
typeof resource === 'object' | ||
? [ action, resource.kind, resource.name, resource.id ] | ||
: [ action, resource, id ] | ||
) | ||
.filter( Boolean ) | ||
.join( '/' ); | ||
for ( const action of ALLOWED_RESOURCE_ACTIONS ) { | ||
const key = getUserPermissionCacheKey( action, resource, id ); | ||
|
||
dispatch.receiveUserPermission( key, permissions[ action ] ); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated change showcases the benefits of this proposal. I am happy to extract it into a separate PR.
Requests before with four pattern blocks on canvas:
Requests after: