@@ -34,6 +34,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
3434 */
3535 protected $ meta ;
3636
37+ /**
38+ * Passwordless post access permitted.
39+ *
40+ * @since 5.7.1
41+ * @var int[]
42+ */
43+ protected $ password_check_passed = array ();
44+
3745 /**
3846 * Constructor.
3947 *
@@ -142,6 +150,38 @@ public function get_items_permissions_check( $request ) {
142150 return true ;
143151 }
144152
153+ /**
154+ * Override the result of the post password check for REST requested posts.
155+ *
156+ * Allow users to read the content of password protected posts if they have
157+ * previously passed a permission check or if they have the `edit_post` capability
158+ * for the post being checked.
159+ *
160+ * @since 5.7.1
161+ *
162+ * @param bool $required Whether the post requires a password check.
163+ * @param WP_Post $post The post been password checked.
164+ * @return bool Result of password check taking in to account REST API considerations.
165+ */
166+ public function check_password_required ( $ required , $ post ) {
167+ if ( ! $ required ) {
168+ return $ required ;
169+ }
170+
171+ $ post = get_post ( $ post );
172+
173+ if ( ! $ post ) {
174+ return $ required ;
175+ }
176+
177+ if ( ! empty ( $ this ->password_check_passed [ $ post ->ID ] ) ) {
178+ // Password previously checked and approved.
179+ return false ;
180+ }
181+
182+ return ! current_user_can ( 'edit_post ' , $ post ->ID );
183+ }
184+
145185 /**
146186 * Retrieves a collection of posts.
147187 *
@@ -298,7 +338,7 @@ public function get_items( $request ) {
298338
299339 // Allow access to all password protected posts if the context is edit.
300340 if ( 'edit ' === $ request ['context ' ] ) {
301- add_filter ( 'post_password_required ' , ' __return_false ' );
341+ add_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ), 10 , 2 );
302342 }
303343
304344 $ posts = array ();
@@ -314,7 +354,7 @@ public function get_items( $request ) {
314354
315355 // Reset filter.
316356 if ( 'edit ' === $ request ['context ' ] ) {
317- remove_filter ( 'post_password_required ' , ' __return_false ' );
357+ remove_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ) );
318358 }
319359
320360 $ page = (int ) $ query_args ['paged ' ];
@@ -408,7 +448,7 @@ public function get_item_permissions_check( $request ) {
408448
409449 // Allow access to all password protected posts if the context is edit.
410450 if ( 'edit ' === $ request ['context ' ] ) {
411- add_filter ( 'post_password_required ' , ' __return_false ' );
451+ add_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ), 10 , 2 );
412452 }
413453
414454 if ( $ post ) {
@@ -437,8 +477,14 @@ public function can_access_password_content( $post, $request ) {
437477 return false ;
438478 }
439479
440- // Edit context always gets access to password-protected posts.
441- if ( 'edit ' === $ request ['context ' ] ) {
480+ /*
481+ * Users always gets access to password protected content in the edit
482+ * context if they have the `edit_post` meta capability.
483+ */
484+ if (
485+ 'edit ' === $ request ['context ' ] &&
486+ current_user_can ( 'edit_post ' , $ post ->ID )
487+ ) {
442488 return true ;
443489 }
444490
@@ -1461,8 +1507,9 @@ public function prepare_item_for_response( $post, $request ) {
14611507 $ has_password_filter = false ;
14621508
14631509 if ( $ this ->can_access_password_content ( $ post , $ request ) ) {
1510+ $ this ->password_check_passed [ $ post ->ID ] = true ;
14641511 // Allow access to the post, permissions already checked before.
1465- add_filter ( 'post_password_required ' , ' __return_false ' );
1512+ add_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ), 10 , 2 );
14661513
14671514 $ has_password_filter = true ;
14681515 }
@@ -1488,7 +1535,7 @@ public function prepare_item_for_response( $post, $request ) {
14881535
14891536 if ( $ has_password_filter ) {
14901537 // Reset filter.
1491- remove_filter ( 'post_password_required ' , ' __return_false ' );
1538+ remove_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ) );
14921539 }
14931540
14941541 if ( ! empty ( $ schema ['properties ' ]['author ' ] ) ) {
0 commit comments