WordPress.org

Make WordPress Core

Ticket #44500: 44500.3.diff

File 44500.3.diff, 15.9 KB (added by desrosj, 2 years ago)
  • src/wp-admin/includes/user.php

     
    778778        $request_ids = $requests_query->posts;
    779779
    780780        foreach ( $request_ids as $request_id ) {
    781                 wp_update_post(
    782                         array(
    783                                 'ID'            => $request_id,
    784                                 'post_status'   => 'request-failed',
    785                                 'post_password' => '',
    786                         )
    787                 );
     781                wp_mark_user_request_failed( $request_id );
    788782        }
    789783}
    790784
  • src/wp-includes/user.php

     
    35283528/**
    35293529 * Validate a user request by comparing the key with the request's key.
    35303530 *
     3531 * If determined that the request is expired, it will be transitioned to the `request-failed` status.
     3532 *
    35313533 * @since 4.9.6
    35323534 *
    35333535 * @param string $request_id ID of the request being confirmed.
     
    35833585        }
    35843586
    35853587        if ( ! $expiration_time || time() > $expiration_time ) {
     3588                wp_mark_user_request_failed( $request_id );
    35863589                return new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) );
    35873590        }
    35883591
     
    36093612}
    36103613
    36113614/**
     3615 * Marks a user_request post as failed.
     3616 *
     3617 * @since 4.9.9
     3618 *
     3619 * @param int $request_id User request ID.
     3620 * @return int|WP_Error Post ID when updated successfully, WP_Error on failure.
     3621 */
     3622function wp_mark_user_request_failed( $request_id ) {
     3623        $post = get_post( $request_id );
     3624
     3625        if ( ! $post ) {
     3626                return new WP_Error( 'invalid_request_id',  __( 'Invalid request ID.' ) );
     3627        } elseif ('user_request' !== $post->post_type ) {
     3628                return new WP_Error( 'invalid_post_type', __( 'Invalid request post type.' ) );
     3629        }
     3630
     3631        if ( 'request-completed' === $post->post_status ) {
     3632                return new WP_Error( 'already_completed', __( 'The request has already been completed.' ) );
     3633        }
     3634
     3635        return wp_update_post(
     3636                array(
     3637                        'ID'            => $request_id,
     3638                        'post_status'   => 'request-failed',
     3639                        'post_password' => '',
     3640                ),
     3641                true
     3642        );
     3643}
     3644
     3645/**
    36123646 * WP_User_Request class.
    36133647 *
    36143648 * Represents user request data loaded from a WP_Post object.
  • tests/phpunit/tests/privacy/wpPersonalDataCleanupRequests.php

     
     1<?php
     2/**
     3 * Test the `_wp_personal_data_cleanup_requests()` function.
     4 *
     5 * @package WordPress
     6 * @subpackage UnitTests
     7 * @since 4.9.9
     8 */
     9
     10/**
     11 * Tests_WpPersonalDataCleanupRequests class.
     12 *
     13 * @group privacy
     14 * @covers wp_mark_user_request_failed
     15 *
     16 * @since 4.9.9
     17 */
     18class Tests_WpPersonalDataCleanupRequests extends WP_UnitTestCase {
     19
     20        /**
     21         * Utility method for creating user requests.
     22         *
     23         * @since 4.9.9
     24         *
     25         * @param int   $number Number of posts to create. Default is 4.
     26         * @param array $args   Post arguments. Default is none. @see wp_insert_post().
     27         */
     28        public function _create_requests( $number = 4, $args = array() ) {
     29                $defaults = array(
     30                        'post_type'   => 'user_request',
     31                        'post_name'   => 'export_personal_data',
     32                        'post_status' => 'request-pending',
     33                );
     34                $args     = wp_parse_args( $args, $defaults );
     35                $this->factory->post->create_many( $number, $args );
     36        }
     37
     38        /**
     39         * Utility method for getting a list of request IDs with a given status.
     40         *
     41         * @since 4.9.9
     42         *
     43         * @param string $status Request status to query. Default is pending.
     44         * @return array List of request post IDs.
     45         */
     46        public function _get_request_ids( $status = 'request-pending' ) {
     47                $failed_requests = new WP_Query(
     48                        array(
     49                                'post_type'      => 'user_request',
     50                                'post_status'    => $status,
     51                                'fields'         => 'ids',
     52                                'posts_per_page' => 100,
     53                        )
     54                );
     55
     56                return $failed_requests->posts;
     57        }
     58
     59        /**
     60         * The function should not mark unexpired requests as failed.
     61         *
     62         * @ticket 44500
     63         */
     64        public function test_function_does_not_move_pending_requests_with_time_remaining() {
     65                $this->_create_requests();
     66
     67                _wp_personal_data_cleanup_requests();
     68
     69                $this->assertSame( 4, count( $this->_get_request_ids() ) );
     70                $this->assertSame( 0, count( $this->_get_request_ids( 'request-failed' ) ) );
     71        }
     72
     73        /**
     74         * The function should mark all unexpired requests as failed.
     75         *
     76         * @ticket 44500
     77         */
     78        public function test_function_moves_all_expired_pending_requests() {
     79                $this->_create_requests( 4, array(
     80                        'post_date' => date( 'Y-m-d H:i:s', strtotime( '4 days ago' ) ),
     81                ) );
     82
     83                _wp_personal_data_cleanup_requests();
     84
     85                $this->assertSame( 0, count( $this->_get_request_ids() ) );
     86                $this->assertSame( 4, count( $this->_get_request_ids( 'request-failed' ) ) );
     87        }
     88
     89        /**
     90         * The function should only mark expired requests as failed when there is a mix, even if requests with other
     91         * statuses would be considered expired.
     92         *
     93         * @ticket 44500
     94         */
     95        public function test_function_udpates_correct_requests_with_mixed_status_requests() {
     96                $this->_create_requests( 2 );
     97                $this->_create_requests( 2, array(
     98                        'post_date'   => date( 'Y-m-d H:i:s', strtotime( '5 days ago' ) ),
     99                        'post_status' => 'request-completed',
     100                ) );
     101                $this->_create_requests( 2, array(
     102                        'post_date' => date( 'Y-m-d H:i:s', strtotime( '4 days ago' ) ),
     103                ) );
     104
     105                _wp_personal_data_cleanup_requests();
     106
     107                $this->assertSame( 2, count( $this->_get_request_ids() ) );
     108                $this->assertSame( 2, count( $this->_get_request_ids( 'request-completed' ) ) );
     109                $this->assertSame( 2, count( $this->_get_request_ids( 'request-failed' ) ) );
     110        }
     111
     112        /**
     113         * The function should mark only expired requests as failed, even when there are export and erase requests mixed.
     114         *
     115         * @ticket 44500
     116         */
     117        public function test_function_updates_correct_requests_with_mixed_export_erase() {
     118                $this->_create_requests( 2 );
     119                $this->_create_requests( 2, array(
     120                        'post_name' => 'remove_personal_data',
     121                ) );
     122                $this->_create_requests( 2, array(
     123                        'post_date' => date( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
     124                ) );
     125                $this->_create_requests( 2, array(
     126                        'post_name' => 'remove_personal_data',
     127                        'post_date' => date( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
     128                ) );
     129
     130                add_filter( 'user_request_key_expiration', array( $this, 'filter_request_expiration_time' ) );
     131                _wp_personal_data_cleanup_requests();
     132
     133                $this->assertSame( 4, count( $this->_get_request_ids() ) );
     134                $this->assertSame( 4, count( $this->_get_request_ids( 'request-failed' ) ) );
     135        }
     136
     137        /**
     138         * The function should mark only expired requests as failed when the expiration time is filtered.
     139         *
     140         * @ticket 44500
     141         */
     142        public function test_function_updates_correct_requests_with_filtered_expiration() {
     143                $this->_create_requests( 2 );
     144                $this->_create_requests( 2, array(
     145                        'post_status' => 'request-completed',
     146                        'post_date'   => date( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
     147                ) );
     148                $this->_create_requests( 2, array(
     149                        'post_date' => date( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
     150                ) );
     151
     152                add_filter( 'user_request_key_expiration', array( $this, 'filter_request_expiration_time' ) );
     153                _wp_personal_data_cleanup_requests();
     154
     155                $this->assertSame( 2, count( $this->_get_request_ids() ) );
     156                $this->assertSame( 2, count( $this->_get_request_ids( 'request-completed' ) ) );
     157                $this->assertSame( 2, count( $this->_get_request_ids( 'request-failed' ) ) );
     158        }
     159
     160        /**
     161         * Filter the privacy data request expiration time.
     162         *
     163         * @since 4.9.9
     164         *
     165         * @return int Expiration time in seconds
     166         */
     167        public function filter_request_expiration_time() {
     168                return DAY_IN_SECONDS * 1;
     169        }
     170}
  • tests/phpunit/tests/user/wpMarkUserRequestFailed.php

     
     1<?php
     2/**
     3 * Test the `wp_mark_user_request_failed()` function.
     4 *
     5 * @package WordPress
     6 * @subpackage UnitTests
     7 * @since 4.9.9
     8 */
     9
     10/**
     11 * Tests_WpMarkUserRequestFailed class.
     12 *
     13 * @group privacy
     14 * @ticket 44500
     15
     16 * @covers wp_mark_user_request_failed
     17 *
     18 * @since 4.9.9
     19 */
     20class Tests_WpMarkUserRequestFailed extends WP_UnitTestCase {
     21        /**
     22         * Current test request ID.
     23         *
     24         * @since 4.9.9
     25         *
     26         * @var int $request_id
     27         */
     28        protected static $request_id;
     29
     30        /**
     31         * Create fixtures.
     32         *
     33         * @since 4.9.9
     34         */
     35        public function setUp() {
     36                parent::setUp();
     37
     38                self::$request_id = wp_create_user_request( 'requester@example.com', 'export_personal_data' );
     39        }
     40
     41        /**
     42         * The function should return an error when an invalid request post ID is passed.
     43         *
     44         * @since 4.9.9
     45         */
     46        public function test_function_throws_error_when_invalid_request_id() {
     47                $actual = wp_mark_user_request_failed( null );
     48
     49                $this->assertWPError( $actual );
     50                $this->assertSame( 'Invalid request ID.', $actual->get_error_message() );
     51        }
     52
     53        /**
     54         * The function should return an error when an invalid request post ID is passed.
     55         *
     56         * @ticket 44500
     57         */
     58        public function test_function_throws_error_when_invalid_request_type() {
     59                $non_request_post_id = $this->factory->post->create(
     60                        array(
     61                                'post_type' => 'post',
     62                        )
     63                );
     64
     65                $actual = wp_mark_user_request_failed( $non_request_post_id );
     66
     67                $this->assertWPError( $actual );
     68                $this->assertSame( 'Invalid request post type.', $actual->get_error_message() );
     69        }
     70
     71        /**
     72         * The function should return an error when the request has already been completed.
     73         *
     74         * @ticket 44500
     75         */
     76        public function test_function_throws_error_when_request_already_completed() {
     77                wp_update_post(
     78                        array(
     79                                'ID'          => self::$request_id,
     80                                'post_status' => 'request-completed',
     81                        )
     82                );
     83
     84                $actual = wp_mark_user_request_failed( self::$request_id );
     85
     86                $this->assertWPError( $actual );
     87                $this->assertSame( 'The request has already been completed.', $actual->get_error_message() );
     88        }
     89
     90        /**
     91         * The function should return an error when an invalid request post ID is passed.
     92         *
     93         * @ticket 44500
     94         */
     95        public function test_function_succeeds() {
     96                $actual = wp_mark_user_request_failed( self::$request_id );
     97
     98                $this->assertSame( self::$request_id, $actual );
     99                $this->assertSame( 'request-failed', get_post_status( self::$request_id ) );
     100        }
     101}
  • tests/phpunit/tests/user/wpValidateUserRequestKey.php

     
     1<?php
     2/**
     3 * Test the `wp_validate_user_request_key()` function.
     4 *
     5 * @package WordPress
     6 * @subpackage UnitTests
     7 * @since 4.9.9
     8 */
     9
     10/**
     11 * Tests_WpValidateUserRequestKey class.
     12 *
     13 * @group user
     14 * @group privacy
     15 * @covers wp_validate_user_request_key
     16 *
     17 * @since 4.9.9
     18 */
     19class Tests_WpValidateUserRequestKey extends WP_UnitTestCase {
     20        /**
     21         * Request ID
     22         *
     23         * @since 4.9.9
     24         *
     25         * @var int $request_id
     26         */
     27        protected static $request_id;
     28
     29        /**
     30         * Request confirmation key.
     31         *
     32         * @since 4.9.9
     33         *
     34         * @var string $request_key
     35         */
     36        protected static $request_key;
     37
     38        /**
     39         * Create fixtures.
     40         *
     41         * @since 4.9.9
     42         *
     43         * @param WP_UnitTest_Factory $factory Factory.
     44         */
     45        public static function wpSetUpBeforeClass( $factory ) {
     46                self::$request_id  = wp_create_user_request( 'requester@example.com', 'export_personal_data' );
     47                self::$request_key = wp_generate_user_request_key( self::$request_id );
     48        }
     49
     50        /**
     51         * A WP_Error should be returned when an invalid request ID value is passed.
     52         *
     53         * @ticket 44500
     54         */
     55        public function test_invalid_request() {
     56                $actual = wp_validate_user_request_key( null, self::$request_key );
     57
     58                $this->assertWPError( $actual );
     59                $this->assertSame( 'invalid_request', $actual->get_error_code() );
     60        }
     61
     62        /**
     63         * A WP_Error should be returned when a request ID that does not exist.
     64         *
     65         * @ticket 44500
     66         */
     67        public function test_invalid_request_does_not_exist() {
     68                $actual = wp_validate_user_request_key( 1234567, self::$request_key );
     69
     70                $this->assertWPError( $actual );
     71                $this->assertSame( 'invalid_request', $actual->get_error_code() );
     72        }
     73
     74        /**
     75         * A WP_Error should be returned when the request is not pending or failed.
     76         *
     77         * @ticket 44500
     78         */
     79        public function test_request_not_pending_or_failed() {
     80                wp_update_post(
     81                        array(
     82                                'ID'          => self::$request_id,
     83                                'post_status' => 'request-confirmed',
     84                        )
     85                );
     86
     87                $actual = wp_validate_user_request_key( self::$request_id, self::$request_key );
     88
     89                $this->assertWPError( $actual );
     90                $this->assertSame( 'expired_link', $actual->get_error_code() );
     91        }
     92
     93        /**
     94         * A WP_Error should be returned when an empty key is passed.
     95         *
     96         * @ticket 44500
     97         */
     98        public function test_empty_key() {
     99                $actual = wp_validate_user_request_key( self::$request_id, '' );
     100
     101                $this->assertWPError( $actual );
     102                $this->assertSame( 'invalid_key', $actual->get_error_code() );
     103        }
     104
     105        /**
     106         * A WP_Error should be returned when a request does not have a confirmation key stored.
     107         *
     108         * @ticket 44500
     109         */
     110        public function test_empty_post_password() {
     111                wp_update_post(
     112                        array(
     113                                'ID'            => self::$request_id,
     114                                'post_password' => '',
     115                        )
     116                );
     117
     118                $actual = wp_validate_user_request_key( self::$request_id, self::$request_key );
     119
     120                $this->assertWPError( $actual );
     121                $this->assertSame( 'invalid_key', $actual->get_error_code() );
     122        }
     123
     124        /**
     125         * A WP_Error should be returned when the passed key does not match.
     126         *
     127         * @ticket 44500
     128         */
     129        public function test_mismatched_keys() {
     130                $actual = wp_validate_user_request_key( self::$request_id, 'abcdefg' );
     131
     132                $this->assertWPError( $actual );
     133                $this->assertSame( 'invalid_key', $actual->get_error_code() );
     134        }
     135
     136        /**
     137         * A WP_Error should be returned when key has expired.
     138         *
     139         * @ticket 44500
     140         */
     141        public function test_expired_key() {
     142                global $wpdb;
     143
     144                $wpdb->update(
     145                        $wpdb->posts,
     146                        array(
     147                                'post_modified_gmt' => gmdate( 'Y-m-d H:i:s', ( time() - 5 * DAY_IN_SECONDS ) ),
     148                        ),
     149                        array(
     150                                'ID' => self::$request_id,
     151                        )
     152                );
     153
     154                $actual = wp_validate_user_request_key( self::$request_id, self::$request_key );
     155
     156                $this->assertWPError( $actual );
     157                $this->assertSame( 'expired_key', $actual->get_error_code() );
     158        }
     159
     160        /**
     161         * A WP_Error should be returned when the key has expired and the expiration time is filtered.
     162         *
     163         * @ticket 44500
     164         */
     165        public function test_expired_key_filtered() {
     166                global $wpdb;
     167
     168                $wpdb->update(
     169                        $wpdb->posts,
     170                        array(
     171                                'post_modified_gmt' => gmdate( 'Y-m-d H:i:s', ( time() - 2 * DAY_IN_SECONDS ) ),
     172                        ),
     173                        array(
     174                                'ID' => self::$request_id,
     175                        )
     176                );
     177
     178                add_filter( 'user_request_key_expiration', array( $this, 'filter_request_key_expiration' ) );
     179                $actual = wp_validate_user_request_key( self::$request_id, self::$request_key );
     180
     181                $this->assertWPError( $actual );
     182                $this->assertSame( 'expired_key', $actual->get_error_code() );
     183        }
     184
     185        /**
     186         * Filter the key expiration time.
     187         *
     188         * @since 4.9.9
     189         *
     190         * @param $expiration Expiration time in seconds.
     191         * @return int New expiration time.
     192         */
     193        public function filter_request_key_expiration( $expiration ) {
     194                return DAY_IN_SECONDS;
     195        }
     196
     197        /**
     198         * Test a key validation that should succeed.
     199         *
     200         * @ticket 44500
     201         */
     202        public function test_key_validates() {
     203                $this->assertTrue( wp_validate_user_request_key( self::$request_id, self::$request_key ) );
     204        }
     205
     206        /**
     207         * Test an erase request key validation that should succeed.
     208         *
     209         * @ticket 44500
     210         */
     211        public function test_key_validates_erase() {
     212                wp_update_post(
     213                        array(
     214                                'ID'        => self::$request_id,
     215                                'post_name' => 'remove_personal_data'
     216                        )
     217                );
     218
     219                $this->assertTrue( wp_validate_user_request_key( self::$request_id, self::$request_key ) );
     220        }
     221}