What is the proper way to validate and sanitize JSON response from REST API?

I have read the WordPress page about this but didn’t find a solution.

Here are my details:

register rest route:

register_rest_route(
    '/jwt-auth/v1',
    '/user',
    array(
        'methods'             => array( 'GET', 'POST', 'PUT' ),
        'callback'            => array( $this, 'user_get_information' ),
        'permission_callback' => function() {
            return is_user_logged_in();
        },
    ),
);

user function :

public function user_get_information( $request ) {
    $user_id = get_current_user_id();
    $data    = array();
    if ( filter_input( INPUT_SERVER, 'REQUEST_METHOD' ) === 'POST' ) {
        $params = array(
            'nickname',
            'first_name',
            'last_name',
            'mobile',
            'favorites',
            'playtime',
        );

        $allreq = $request->get_params();

        foreach ( $allreq as $req => $val ) {
            if ( ! empty( $val ) && in_array( $req, $params, true ) ) {
                if ( 'favorites' === $req ) {
                    // do somthing
                } elseif ( 'playtime' === $req ) { 

// i want this json data validate and sanitize then add to database

                    $meta      = get_user_meta( $user_id, 'playtime', true );
                    $schema    = $this->user_playtime_meta_schema();
                    if ( rest_validate_value_from_schema( $val, $schema ) ) {
                        $sanitized = rest_sanitize_value_from_schema( $val, $schema );
                    }
                    if ( ! is_array( $meta ) ) {
                        $meta = array();
                    }
                    $meta[] = $sanitized;
                    // $meta = array();
                } else {
                    $meta = $val;
                }
                $user_meta = update_user_meta( $user_id, 'playtime', $meta );
            }
        }
    }
    if ( is_wp_error( $user_meta ) ) {
        $error_string = $user_meta->get_error_message();
        return $error_string;
    } else {
        $info   = get_user_by( 'ID', $user_id );
        $meta   = get_user_meta( $user_id );
        $img_id = $meta['image_select'][0];
        if ( $img_id ) {
            $img_url = wp_get_attachment_url( $img_id );
        }
        $data['id']           = $info->ID;
        $data['login']        = $info->user_login;
        $data['email']        = $info->user_email;
        $data['display_name'] = $info->display_name;
        $data['image']        = $img_url;
        $data['nickname']     = $meta['nickname'][0];
        $data['first_name']   = $meta['first_name'][0];
        $data['last_name']    = $meta['last_name'][0];
        $data['mobile']       = $meta['mobile'][0];
        $data['favorites']    = get_user_meta( $user_id, 'favorites', true );
        $data['playtime']     = get_user_meta( $user_id, 'playtime', true );
        return $data;
    }
}

schema :

public function user_playtime_meta_schema() {
    if ( $this->playtime_schema ) {
        return $this->playtime_schema;
    }
    $this->playtime_schema = array(
        'type' => array(
            'type'       => 'object',
            'properties' => array(
                'song'     => array(
                    'type'       => 'object',
                    'properties' => array(
                        'name'  => array(
                            'type' => 'string',
                        ),
                        'id'    => array(
                            'type' => 'number',
                        ),
                        'notes' => array(
                            'type' => 'number',
                        ),
                    ),
                ),
                'time'     => array(
                    'type' => 'string',
                ),
                'date'     => array(
                    'type' => 'string',
                ),
                'score'    => array(
                    'type' => 'string',
                ),
                'progress' => array(
                    'type' => 'string',
                ),
            ),
        ),
    );
    return $this->playtime_schema;
}

try send data like this:

{"playtime":{"song": {
        "name": "Training New",
        "id": 758,
        "notes": 65
    },
    "time": "10:27:19 PM",
    "score": "[[76,"perfect"],[74,"perfect"],[77,"perfect"],[76,"perfect"],[74,"late"],[72,"late"],[74,"perfect"],[76,"perfect"],[76,"perfect"],[76,"perfect"],[74,"perfect"],[77,"perfect"],[76,"late"],[74,"late"],[72,"perfect"],[74,"perfect"],[76,"perfect"],[76,"perfect"],[74,"perfect"],[72,"perfect"],[71,"perfect"],[67,"perfect"],[74,"perfect"],[72,"perfect"],[74,"perfect"],[71,"perfect"],[72,"perfect"],[74,"late"],[71,"perfect"],[72,"perfect"],[71,"late"],[67,"perfect"]]",
    "date": "8/17/2020",
    "progress": "4%"}
}

everything works , but if i send some bad information like this :

    {"playtime":{"wrong": {
        "number": "1",
        "notes": 525
    },
    "time": "10:27:19 PM",
    "progress": "4%"}
}

also works and wrong data would be saved in database!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Thanks to @GTsvetanov from Stackoverflow.com.

Missing part of my code is $request->get_json_params(); for getting json request then compare it with schema using rest_validate_value_from_schema() then using rest_sanitize_value_from_schema() for saving proper data to database.

    $schema = $this->user_playtime_meta_schema();
    $val    = $request->get_json_params();//<-- my mistake
    $result = rest_validate_value_from_schema( $values, $schema );
    if ( ! is_wp_error( rest_validate_value_from_schema( $val, $schema ) ) ) {
        $sanitized = rest_sanitize_value_from_schema( $val, $schema );
    } else {
        return $result;
    }
    $user_meta = update_user_meta( $user_id, 'playtime', $sanitized );


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x