-
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: Add support for fetching permissions of custom actions #18956
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -127,8 +127,8 @@ export function* hasUploadPermissions() { | |||||
* Checks whether the current user can perform the given action on the given | ||||||
* REST resource. | ||||||
* | ||||||
* @param {string} action Action to check. One of: 'create', 'read', 'update', | ||||||
* 'delete'. | ||||||
* @param {string} action Action to check. One of 'create', 'read', 'update', | ||||||
* 'delete', or a JSON Hyper Schema targetSchema key. | ||||||
* @param {string} resource REST resource to check, e.g. 'media' or 'posts'. | ||||||
* @param {?string} id ID of the rest resource to check. | ||||||
*/ | ||||||
|
@@ -140,43 +140,61 @@ export function* canUser( action, resource, id ) { | |||||
delete: 'DELETE', | ||||||
}; | ||||||
|
||||||
const method = methods[ action ]; | ||||||
if ( ! method ) { | ||||||
throw new Error( `'${ action }' is not a valid action.` ); | ||||||
const isCustomAction = ! methods.hasOwnProperty( action ); | ||||||
|
||||||
let path = '/wp/v2/' + resource; | ||||||
|
||||||
if ( id ) { | ||||||
path += '/' + id; | ||||||
} | ||||||
|
||||||
const path = id ? `/wp/v2/${ resource }/${ id }` : `/wp/v2/${ resource }`; | ||||||
if ( isCustomAction ) { | ||||||
path = addQueryArgs( path, { context: 'edit' } ); | ||||||
} | ||||||
|
||||||
let response; | ||||||
try { | ||||||
response = yield apiFetch( { | ||||||
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 | ||||||
// OPTIONS requests to /posts/:id routes. | ||||||
// https://core.trac.wordpress.org/ticket/45753 | ||||||
method: id ? 'GET' : 'OPTIONS', | ||||||
parse: false, | ||||||
// Ideally, this should only be a GET request if requesting details | ||||||
// of a custom action. Until required WordPress support reaches 5.3 | ||||||
// or newer, the `id` condition must be included, due to a previous | ||||||
// bug in the REST API where the Allow header was not on OPTIONS | ||||||
// requests to /posts/:id routes. | ||||||
// | ||||||
// See: https://core.trac.wordpress.org/ticket/45753 | ||||||
method: id || isCustomAction ? 'GET' : 'OPTIONS', | ||||||
|
||||||
// Only parse response as JSON if requesting permissions of a custom | ||||||
// actions. Non-custom actions derive permissions from the response | ||||||
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.
Suggested change
|
||||||
// headers, which aren't available on the parsed result. | ||||||
parse: isCustomAction, | ||||||
} ); | ||||||
} catch ( error ) { | ||||||
// Do nothing if our OPTIONS request comes back with an API error (4xx or | ||||||
// 5xx). The previously determined isAllowed value will remain in the store. | ||||||
return; | ||||||
} | ||||||
|
||||||
let allowHeader; | ||||||
if ( hasIn( response, [ 'headers', 'get' ] ) ) { | ||||||
// If the request is fetched using the fetch api, the header can be | ||||||
// retrieved using the 'get' method. | ||||||
allowHeader = response.headers.get( 'allow' ); | ||||||
let isAllowed; | ||||||
if ( isCustomAction ) { | ||||||
isAllowed = hasIn( response, [ '_links', 'wp:action-' + action ] ); | ||||||
} else { | ||||||
// If the request was preloaded server-side and is returned by the | ||||||
// preloading middleware, the header will be a simple property. | ||||||
allowHeader = get( response, [ 'headers', 'Allow' ], '' ); | ||||||
let allowHeader; | ||||||
if ( hasIn( response, [ 'headers', 'get' ] ) ) { | ||||||
// If the request is fetched using the fetch api, the header can be | ||||||
// retrieved using the 'get' method. | ||||||
allowHeader = response.headers.get( 'allow' ); | ||||||
} else { | ||||||
// If the request was preloaded server-side and is returned by the | ||||||
// preloading middleware, the header will be a simple property. | ||||||
allowHeader = get( response, [ 'headers', 'Allow' ], '' ); | ||||||
} | ||||||
|
||||||
isAllowed = includes( allowHeader, methods[ action ] ); | ||||||
} | ||||||
|
||||||
const key = compact( [ action, resource, id ] ).join( '/' ); | ||||||
const isAllowed = includes( allowHeader, method ); | ||||||
yield receiveUserPermission( key, isAllowed ); | ||||||
} | ||||||
|
||||||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -158,6 +158,32 @@ describe( 'canUser', () => { | |
expect( received.done ).toBe( true ); | ||
expect( received.value ).toBeUndefined(); | ||
} ); | ||
|
||
it( 'receives custom actions', () => { | ||
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. Nice! |
||
const generator = canUser( 'publish', 'posts' ); | ||
|
||
let received = generator.next(); | ||
expect( received.done ).toBe( false ); | ||
expect( received.value ).toEqual( apiFetch( { | ||
path: '/wp/v2/posts?context=edit', | ||
method: 'GET', | ||
parse: true, | ||
} ) ); | ||
|
||
received = generator.next( { | ||
_links: { | ||
'wp:action-publish': [ | ||
{ href: 'http://localhost:8888/wp-json/wp/v2/posts' }, | ||
], | ||
}, | ||
} ); | ||
expect( received.done ).toBe( false ); | ||
expect( received.value ).toEqual( receiveUserPermission( 'publish/posts', true ) ); | ||
|
||
received = generator.next(); | ||
expect( received.done ).toBe( true ); | ||
expect( received.value ).toBeUndefined(); | ||
} ); | ||
} ); | ||
|
||
describe( 'getAutosaves', () => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
We don't want to add
"undefined"
whenresource
and/orid
are undefined.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.
resource
should be considered a required parameter.id
is optional†, but this concatenation occurs in a condition to consider it as being set.† The JSDoc should be updated from the nullable
{?string}
type to the correct[id]
optional parameter notation.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.
What if I want to request the root/index resource?
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.
You would omit the
id
parameter.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.
I think I might not be understanding what you're asking. There will always be a resource.
When I say it doesn't necessarily need to be a singular resource, I consider it the same as how it might map to a use of
current_user_can
in PHP:https://developer.wordpress.org/reference/functions/current_user_can/
I see this mapping to
canUser
as something like:The caveat mentioned in the original post is that, currently, the REST API only supports the latter of these two, since it only includes action
_links
on the response of an item:https://github.com/WordPress/wordpress-develop/blob/47e38ea/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L1675-L1683
My thinking is that, to represent the first of these (without an ID), it could be possible to include the action
_links
properties on the collection response as well:https://github.com/WordPress/wordpress-develop/blob/47e38ea/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L155
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.
Right, but we also have a base resource:
f6ce79c#diff-c5eaec560b039f2dc76f93fa76ba89da
Aren't there capabilities for
/wp/v2/
or/
?I still think that
canUser
should have the same API asgetEntityRecord
withkind
andname
and we can just grab the resource from the entity config as I outlined here: #18956 (review).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.
Doesn't seem to me like there would be.
I agree this should be a goal for reuse. Not entirely sure yet how I feel about the overloaded signature, or if it's something to reevaluate whether "resource" is ever a sufficient parameter (i.e. might be more inclined to deprecate this parameter in favor of
kind
,name
, if it came to it, or perhaps vice versa).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.
Oh, I never meant to have an overloaded signature. I was suggesting to deprecate "resource".