@@ -32,6 +32,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
3232 */
3333 protected $ meta ;
3434
35+ /**
36+ * Passwordless post access permitted.
37+ *
38+ * @since 5.7.1
39+ * @var int[]
40+ */
41+ protected $ password_check_passed = array ();
42+
3543 /**
3644 * Constructor.
3745 *
@@ -137,6 +145,38 @@ public function get_items_permissions_check( $request ) {
137145 return true ;
138146 }
139147
148+ /**
149+ * Override the result of the post password check for REST requested posts.
150+ *
151+ * Allow users to read the content of password protected posts if they have
152+ * previously passed a permission check or if they have the `edit_post` capability
153+ * for the post being checked.
154+ *
155+ * @since 5.7.1
156+ *
157+ * @param bool $required Whether the post requires a password check.
158+ * @param WP_Post $post The post been password checked.
159+ * @return bool Result of password check taking in to account REST API considerations.
160+ */
161+ public function check_password_required ( $ required , $ post ) {
162+ if ( ! $ required ) {
163+ return $ required ;
164+ }
165+
166+ $ post = get_post ( $ post );
167+
168+ if ( ! $ post ) {
169+ return $ required ;
170+ }
171+
172+ if ( ! empty ( $ this ->password_check_passed [ $ post ->ID ] ) ) {
173+ // Password previously checked and approved.
174+ return false ;
175+ }
176+
177+ return ! current_user_can ( 'edit_post ' , $ post ->ID );
178+ }
179+
140180 /**
141181 * Retrieves a collection of posts.
142182 *
@@ -292,7 +332,7 @@ public function get_items( $request ) {
292332
293333 // Allow access to all password protected posts if the context is edit.
294334 if ( 'edit ' === $ request ['context ' ] ) {
295- add_filter ( 'post_password_required ' , ' __return_false ' );
335+ add_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ), 10 , 2 );
296336 }
297337
298338 $ posts = array ();
@@ -308,7 +348,7 @@ public function get_items( $request ) {
308348
309349 // Reset filter.
310350 if ( 'edit ' === $ request ['context ' ] ) {
311- remove_filter ( 'post_password_required ' , ' __return_false ' );
351+ remove_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ) );
312352 }
313353
314354 $ page = (int ) $ query_args ['paged ' ];
@@ -406,7 +446,7 @@ public function get_item_permissions_check( $request ) {
406446
407447 // Allow access to all password protected posts if the context is edit.
408448 if ( 'edit ' === $ request ['context ' ] ) {
409- add_filter ( 'post_password_required ' , ' __return_false ' );
449+ add_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ), 10 , 2 );
410450 }
411451
412452 if ( $ post ) {
@@ -434,8 +474,14 @@ public function can_access_password_content( $post, $request ) {
434474 return false ;
435475 }
436476
437- // Edit context always gets access to password-protected posts.
438- if ( 'edit ' === $ request ['context ' ] ) {
477+ /*
478+ * Users always gets access to password protected content in the edit
479+ * context if they have the `edit_post` meta capability.
480+ */
481+ if (
482+ 'edit ' === $ request ['context ' ] &&
483+ current_user_can ( 'edit_post ' , $ post ->ID )
484+ ) {
439485 return true ;
440486 }
441487
@@ -1507,8 +1553,9 @@ public function prepare_item_for_response( $post, $request ) {
15071553 $ has_password_filter = false ;
15081554
15091555 if ( $ this ->can_access_password_content ( $ post , $ request ) ) {
1556+ $ this ->password_check_passed [ $ post ->ID ] = true ;
15101557 // Allow access to the post, permissions already checked before.
1511- add_filter ( 'post_password_required ' , ' __return_false ' );
1558+ add_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ), 10 , 2 );
15121559
15131560 $ has_password_filter = true ;
15141561 }
@@ -1535,7 +1582,7 @@ public function prepare_item_for_response( $post, $request ) {
15351582
15361583 if ( $ has_password_filter ) {
15371584 // Reset filter.
1538- remove_filter ( 'post_password_required ' , ' __return_false ' );
1585+ remove_filter ( 'post_password_required ' , array ( $ this , ' check_password_required ' ) );
15391586 }
15401587
15411588 if ( in_array ( 'author ' , $ fields , true ) ) {
0 commit comments