balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-rest-application-passwords-controller.php (23830B)


      1 <?php
      2 /**
      3  * REST API: WP_REST_Application_Passwords_Controller class
      4  *
      5  * @package    WordPress
      6  * @subpackage REST_API
      7  * @since      5.6.0
      8  */
      9 
     10 /**
     11  * Core class to access a user's application passwords via the REST API.
     12  *
     13  * @since 5.6.0
     14  *
     15  * @see   WP_REST_Controller
     16  */
     17 class WP_REST_Application_Passwords_Controller extends WP_REST_Controller {
     18 
     19 	/**
     20 	 * Application Passwords controller constructor.
     21 	 *
     22 	 * @since 5.6.0
     23 	 */
     24 	public function __construct() {
     25 		$this->namespace = 'wp/v2';
     26 		$this->rest_base = 'users/(?P<user_id>(?:[\d]+|me))/application-passwords';
     27 	}
     28 
     29 	/**
     30 	 * Registers the REST API routes for the application passwords controller.
     31 	 *
     32 	 * @since 5.6.0
     33 	 */
     34 	public function register_routes() {
     35 		register_rest_route(
     36 			$this->namespace,
     37 			'/' . $this->rest_base,
     38 			array(
     39 				array(
     40 					'methods'             => WP_REST_Server::READABLE,
     41 					'callback'            => array( $this, 'get_items' ),
     42 					'permission_callback' => array( $this, 'get_items_permissions_check' ),
     43 					'args'                => $this->get_collection_params(),
     44 				),
     45 				array(
     46 					'methods'             => WP_REST_Server::CREATABLE,
     47 					'callback'            => array( $this, 'create_item' ),
     48 					'permission_callback' => array( $this, 'create_item_permissions_check' ),
     49 					'args'                => $this->get_endpoint_args_for_item_schema(),
     50 				),
     51 				array(
     52 					'methods'             => WP_REST_Server::DELETABLE,
     53 					'callback'            => array( $this, 'delete_items' ),
     54 					'permission_callback' => array( $this, 'delete_items_permissions_check' ),
     55 				),
     56 				'schema' => array( $this, 'get_public_item_schema' ),
     57 			)
     58 		);
     59 
     60 		register_rest_route(
     61 			$this->namespace,
     62 			'/' . $this->rest_base . '/introspect',
     63 			array(
     64 				array(
     65 					'methods'             => WP_REST_Server::READABLE,
     66 					'callback'            => array( $this, 'get_current_item' ),
     67 					'permission_callback' => array( $this, 'get_current_item_permissions_check' ),
     68 					'args'                => array(
     69 						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
     70 					),
     71 				),
     72 				'schema' => array( $this, 'get_public_item_schema' ),
     73 			)
     74 		);
     75 
     76 		register_rest_route(
     77 			$this->namespace,
     78 			'/' . $this->rest_base . '/(?P<uuid>[\w\-]+)',
     79 			array(
     80 				array(
     81 					'methods'             => WP_REST_Server::READABLE,
     82 					'callback'            => array( $this, 'get_item' ),
     83 					'permission_callback' => array( $this, 'get_item_permissions_check' ),
     84 					'args'                => array(
     85 						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
     86 					),
     87 				),
     88 				array(
     89 					'methods'             => WP_REST_Server::EDITABLE,
     90 					'callback'            => array( $this, 'update_item' ),
     91 					'permission_callback' => array( $this, 'update_item_permissions_check' ),
     92 					'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
     93 				),
     94 				array(
     95 					'methods'             => WP_REST_Server::DELETABLE,
     96 					'callback'            => array( $this, 'delete_item' ),
     97 					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
     98 				),
     99 				'schema' => array( $this, 'get_public_item_schema' ),
    100 			)
    101 		);
    102 	}
    103 
    104 	/**
    105 	 * Checks if a given request has access to get application passwords.
    106 	 *
    107 	 * @since 5.6.0
    108 	 *
    109 	 * @param WP_REST_Request $request Full details about the request.
    110 	 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
    111 	 */
    112 	public function get_items_permissions_check( $request ) {
    113 		$user = $this->get_user( $request );
    114 
    115 		if ( is_wp_error( $user ) ) {
    116 			return $user;
    117 		}
    118 
    119 		if ( ! current_user_can( 'list_app_passwords', $user->ID ) ) {
    120 			return new WP_Error(
    121 				'rest_cannot_list_application_passwords',
    122 				__( 'Sorry, you are not allowed to list application passwords for this user.' ),
    123 				array( 'status' => rest_authorization_required_code() )
    124 			);
    125 		}
    126 
    127 		return true;
    128 	}
    129 
    130 	/**
    131 	 * Retrieves a collection of application passwords.
    132 	 *
    133 	 * @since 5.6.0
    134 	 *
    135 	 * @param WP_REST_Request $request Full details about the request.
    136 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    137 	 */
    138 	public function get_items( $request ) {
    139 		$user = $this->get_user( $request );
    140 
    141 		if ( is_wp_error( $user ) ) {
    142 			return $user;
    143 		}
    144 
    145 		$passwords = WP_Application_Passwords::get_user_application_passwords( $user->ID );
    146 		$response  = array();
    147 
    148 		foreach ( $passwords as $password ) {
    149 			$response[] = $this->prepare_response_for_collection(
    150 				$this->prepare_item_for_response( $password, $request )
    151 			);
    152 		}
    153 
    154 		return new WP_REST_Response( $response );
    155 	}
    156 
    157 	/**
    158 	 * Checks if a given request has access to get a specific application password.
    159 	 *
    160 	 * @since 5.6.0
    161 	 *
    162 	 * @param WP_REST_Request $request Full details about the request.
    163 	 * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
    164 	 */
    165 	public function get_item_permissions_check( $request ) {
    166 		$user = $this->get_user( $request );
    167 
    168 		if ( is_wp_error( $user ) ) {
    169 			return $user;
    170 		}
    171 
    172 		if ( ! current_user_can( 'read_app_password', $user->ID, $request['uuid'] ) ) {
    173 			return new WP_Error(
    174 				'rest_cannot_read_application_password',
    175 				__( 'Sorry, you are not allowed to read this application password.' ),
    176 				array( 'status' => rest_authorization_required_code() )
    177 			);
    178 		}
    179 
    180 		return true;
    181 	}
    182 
    183 	/**
    184 	 * Retrieves one application password from the collection.
    185 	 *
    186 	 * @since 5.6.0
    187 	 *
    188 	 * @param WP_REST_Request $request Full details about the request.
    189 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    190 	 */
    191 	public function get_item( $request ) {
    192 		$password = $this->get_application_password( $request );
    193 
    194 		if ( is_wp_error( $password ) ) {
    195 			return $password;
    196 		}
    197 
    198 		return $this->prepare_item_for_response( $password, $request );
    199 	}
    200 
    201 	/**
    202 	 * Checks if a given request has access to create application passwords.
    203 	 *
    204 	 * @since 5.6.0
    205 	 *
    206 	 * @param WP_REST_Request $request Full details about the request.
    207 	 * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
    208 	 */
    209 	public function create_item_permissions_check( $request ) {
    210 		$user = $this->get_user( $request );
    211 
    212 		if ( is_wp_error( $user ) ) {
    213 			return $user;
    214 		}
    215 
    216 		if ( ! current_user_can( 'create_app_password', $user->ID ) ) {
    217 			return new WP_Error(
    218 				'rest_cannot_create_application_passwords',
    219 				__( 'Sorry, you are not allowed to create application passwords for this user.' ),
    220 				array( 'status' => rest_authorization_required_code() )
    221 			);
    222 		}
    223 
    224 		return true;
    225 	}
    226 
    227 	/**
    228 	 * Creates an application password.
    229 	 *
    230 	 * @since 5.6.0
    231 	 *
    232 	 * @param WP_REST_Request $request Full details about the request.
    233 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    234 	 */
    235 	public function create_item( $request ) {
    236 		$user = $this->get_user( $request );
    237 
    238 		if ( is_wp_error( $user ) ) {
    239 			return $user;
    240 		}
    241 
    242 		$prepared = $this->prepare_item_for_database( $request );
    243 
    244 		if ( is_wp_error( $prepared ) ) {
    245 			return $prepared;
    246 		}
    247 
    248 		$created = WP_Application_Passwords::create_new_application_password( $user->ID, wp_slash( (array) $prepared ) );
    249 
    250 		if ( is_wp_error( $created ) ) {
    251 			return $created;
    252 		}
    253 
    254 		$password = $created[0];
    255 		$item     = WP_Application_Passwords::get_user_application_password( $user->ID, $created[1]['uuid'] );
    256 
    257 		$item['new_password'] = WP_Application_Passwords::chunk_password( $password );
    258 		$fields_update        = $this->update_additional_fields_for_object( $item, $request );
    259 
    260 		if ( is_wp_error( $fields_update ) ) {
    261 			return $fields_update;
    262 		}
    263 
    264 		/**
    265 		 * Fires after a single application password is completely created or updated via the REST API.
    266 		 *
    267 		 * @since 5.6.0
    268 		 *
    269 		 * @param array           $item     Inserted or updated password item.
    270 		 * @param WP_REST_Request $request  Request object.
    271 		 * @param bool            $creating True when creating an application password, false when updating.
    272 		 */
    273 		do_action( 'rest_after_insert_application_password', $item, $request, true );
    274 
    275 		$request->set_param( 'context', 'edit' );
    276 		$response = $this->prepare_item_for_response( $item, $request );
    277 
    278 		$response->set_status( 201 );
    279 		$response->header( 'Location', $response->get_links()['self'][0]['href'] );
    280 
    281 		return $response;
    282 	}
    283 
    284 	/**
    285 	 * Checks if a given request has access to update application passwords.
    286 	 *
    287 	 * @since 5.6.0
    288 	 *
    289 	 * @param WP_REST_Request $request Full details about the request.
    290 	 * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
    291 	 */
    292 	public function update_item_permissions_check( $request ) {
    293 		$user = $this->get_user( $request );
    294 
    295 		if ( is_wp_error( $user ) ) {
    296 			return $user;
    297 		}
    298 
    299 		if ( ! current_user_can( 'edit_app_password', $user->ID, $request['uuid'] ) ) {
    300 			return new WP_Error(
    301 				'rest_cannot_edit_application_password',
    302 				__( 'Sorry, you are not allowed to edit this application password.' ),
    303 				array( 'status' => rest_authorization_required_code() )
    304 			);
    305 		}
    306 
    307 		return true;
    308 	}
    309 
    310 	/**
    311 	 * Updates an application password.
    312 	 *
    313 	 * @since 5.6.0
    314 	 *
    315 	 * @param WP_REST_Request $request Full details about the request.
    316 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    317 	 */
    318 	public function update_item( $request ) {
    319 		$user = $this->get_user( $request );
    320 
    321 		if ( is_wp_error( $user ) ) {
    322 			return $user;
    323 		}
    324 
    325 		$item = $this->get_application_password( $request );
    326 
    327 		if ( is_wp_error( $item ) ) {
    328 			return $item;
    329 		}
    330 
    331 		$prepared = $this->prepare_item_for_database( $request );
    332 
    333 		if ( is_wp_error( $prepared ) ) {
    334 			return $prepared;
    335 		}
    336 
    337 		$saved = WP_Application_Passwords::update_application_password( $user->ID, $item['uuid'], wp_slash( (array) $prepared ) );
    338 
    339 		if ( is_wp_error( $saved ) ) {
    340 			return $saved;
    341 		}
    342 
    343 		$fields_update = $this->update_additional_fields_for_object( $item, $request );
    344 
    345 		if ( is_wp_error( $fields_update ) ) {
    346 			return $fields_update;
    347 		}
    348 
    349 		$item = WP_Application_Passwords::get_user_application_password( $user->ID, $item['uuid'] );
    350 
    351 		/** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php */
    352 		do_action( 'rest_after_insert_application_password', $item, $request, false );
    353 
    354 		$request->set_param( 'context', 'edit' );
    355 		return $this->prepare_item_for_response( $item, $request );
    356 	}
    357 
    358 	/**
    359 	 * Checks if a given request has access to delete all application passwords.
    360 	 *
    361 	 * @since 5.6.0
    362 	 *
    363 	 * @param WP_REST_Request $request Full details about the request.
    364 	 * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
    365 	 */
    366 	public function delete_items_permissions_check( $request ) {
    367 		$user = $this->get_user( $request );
    368 
    369 		if ( is_wp_error( $user ) ) {
    370 			return $user;
    371 		}
    372 
    373 		if ( ! current_user_can( 'delete_app_passwords', $user->ID ) ) {
    374 			return new WP_Error(
    375 				'rest_cannot_delete_application_passwords',
    376 				__( 'Sorry, you are not allowed to delete application passwords for this user.' ),
    377 				array( 'status' => rest_authorization_required_code() )
    378 			);
    379 		}
    380 
    381 		return true;
    382 	}
    383 
    384 	/**
    385 	 * Deletes all application passwords.
    386 	 *
    387 	 * @since 5.6.0
    388 	 *
    389 	 * @param WP_REST_Request $request Full details about the request.
    390 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    391 	 */
    392 	public function delete_items( $request ) {
    393 		$user = $this->get_user( $request );
    394 
    395 		if ( is_wp_error( $user ) ) {
    396 			return $user;
    397 		}
    398 
    399 		$deleted = WP_Application_Passwords::delete_all_application_passwords( $user->ID );
    400 
    401 		if ( is_wp_error( $deleted ) ) {
    402 			return $deleted;
    403 		}
    404 
    405 		return new WP_REST_Response(
    406 			array(
    407 				'deleted' => true,
    408 				'count'   => $deleted,
    409 			)
    410 		);
    411 	}
    412 
    413 	/**
    414 	 * Checks if a given request has access to delete a specific application password.
    415 	 *
    416 	 * @since 5.6.0
    417 	 *
    418 	 * @param WP_REST_Request $request Full details about the request.
    419 	 * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
    420 	 */
    421 	public function delete_item_permissions_check( $request ) {
    422 		$user = $this->get_user( $request );
    423 
    424 		if ( is_wp_error( $user ) ) {
    425 			return $user;
    426 		}
    427 
    428 		if ( ! current_user_can( 'delete_app_password', $user->ID, $request['uuid'] ) ) {
    429 			return new WP_Error(
    430 				'rest_cannot_delete_application_password',
    431 				__( 'Sorry, you are not allowed to delete this application password.' ),
    432 				array( 'status' => rest_authorization_required_code() )
    433 			);
    434 		}
    435 
    436 		return true;
    437 	}
    438 
    439 	/**
    440 	 * Deletes one application password.
    441 	 *
    442 	 * @since 5.6.0
    443 	 *
    444 	 * @param WP_REST_Request $request Full details about the request.
    445 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    446 	 */
    447 	public function delete_item( $request ) {
    448 		$user = $this->get_user( $request );
    449 
    450 		if ( is_wp_error( $user ) ) {
    451 			return $user;
    452 		}
    453 
    454 		$password = $this->get_application_password( $request );
    455 
    456 		if ( is_wp_error( $password ) ) {
    457 			return $password;
    458 		}
    459 
    460 		$request->set_param( 'context', 'edit' );
    461 		$previous = $this->prepare_item_for_response( $password, $request );
    462 		$deleted  = WP_Application_Passwords::delete_application_password( $user->ID, $password['uuid'] );
    463 
    464 		if ( is_wp_error( $deleted ) ) {
    465 			return $deleted;
    466 		}
    467 
    468 		return new WP_REST_Response(
    469 			array(
    470 				'deleted'  => true,
    471 				'previous' => $previous->get_data(),
    472 			)
    473 		);
    474 	}
    475 
    476 	/**
    477 	 * Checks if a given request has access to get the currently used application password.
    478 	 *
    479 	 * @since 5.7.0
    480 	 *
    481 	 * @param WP_REST_Request $request Full details about the request.
    482 	 * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
    483 	 */
    484 	public function get_current_item_permissions_check( $request ) {
    485 		$user = $this->get_user( $request );
    486 
    487 		if ( is_wp_error( $user ) ) {
    488 			return $user;
    489 		}
    490 
    491 		if ( get_current_user_id() !== $user->ID ) {
    492 			return new WP_Error(
    493 				'rest_cannot_introspect_app_password_for_non_authenticated_user',
    494 				__( 'The authenticated Application Password can only be introspected for the current user.' ),
    495 				array( 'status' => rest_authorization_required_code() )
    496 			);
    497 		}
    498 
    499 		return true;
    500 	}
    501 
    502 	/**
    503 	 * Retrieves the application password being currently used for authentication.
    504 	 *
    505 	 * @since 5.7.0
    506 	 *
    507 	 * @param WP_REST_Request $request Full details about the request.
    508 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    509 	 */
    510 	public function get_current_item( $request ) {
    511 		$user = $this->get_user( $request );
    512 
    513 		if ( is_wp_error( $user ) ) {
    514 			return $user;
    515 		}
    516 
    517 		$uuid = rest_get_authenticated_app_password();
    518 
    519 		if ( ! $uuid ) {
    520 			return new WP_Error(
    521 				'rest_no_authenticated_app_password',
    522 				__( 'Cannot introspect Application Password.' ),
    523 				array( 'status' => 404 )
    524 			);
    525 		}
    526 
    527 		$password = WP_Application_Passwords::get_user_application_password( $user->ID, $uuid );
    528 
    529 		if ( ! $password ) {
    530 			return new WP_Error(
    531 				'rest_application_password_not_found',
    532 				__( 'Application password not found.' ),
    533 				array( 'status' => 500 )
    534 			);
    535 		}
    536 
    537 		return $this->prepare_item_for_response( $password, $request );
    538 	}
    539 
    540 	/**
    541 	 * Performs a permissions check for the request.
    542 	 *
    543 	 * @since 5.6.0
    544 	 * @deprecated 5.7.0 Use `edit_user` directly or one of the specific meta capabilities introduced in 5.7.0.
    545 	 *
    546 	 * @param WP_REST_Request $request
    547 	 * @return true|WP_Error
    548 	 */
    549 	protected function do_permissions_check( $request ) {
    550 		_deprecated_function( __METHOD__, '5.7.0' );
    551 
    552 		$user = $this->get_user( $request );
    553 
    554 		if ( is_wp_error( $user ) ) {
    555 			return $user;
    556 		}
    557 
    558 		if ( ! current_user_can( 'edit_user', $user->ID ) ) {
    559 			return new WP_Error(
    560 				'rest_cannot_manage_application_passwords',
    561 				__( 'Sorry, you are not allowed to manage application passwords for this user.' ),
    562 				array( 'status' => rest_authorization_required_code() )
    563 			);
    564 		}
    565 
    566 		return true;
    567 	}
    568 
    569 	/**
    570 	 * Prepares an application password for a create or update operation.
    571 	 *
    572 	 * @since 5.6.0
    573 	 *
    574 	 * @param WP_REST_Request $request Request object.
    575 	 * @return object|WP_Error The prepared item, or WP_Error object on failure.
    576 	 */
    577 	protected function prepare_item_for_database( $request ) {
    578 		$prepared = (object) array(
    579 			'name' => $request['name'],
    580 		);
    581 
    582 		if ( $request['app_id'] && ! $request['uuid'] ) {
    583 			$prepared->app_id = $request['app_id'];
    584 		}
    585 
    586 		/**
    587 		 * Filters an application password before it is inserted via the REST API.
    588 		 *
    589 		 * @since 5.6.0
    590 		 *
    591 		 * @param stdClass        $prepared An object representing a single application password prepared for inserting or updating the database.
    592 		 * @param WP_REST_Request $request  Request object.
    593 		 */
    594 		return apply_filters( 'rest_pre_insert_application_password', $prepared, $request );
    595 	}
    596 
    597 	/**
    598 	 * Prepares the application password for the REST response.
    599 	 *
    600 	 * @since 5.6.0
    601 	 *
    602 	 * @param array           $item    WordPress representation of the item.
    603 	 * @param WP_REST_Request $request Request object.
    604 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    605 	 */
    606 	public function prepare_item_for_response( $item, $request ) {
    607 		$user = $this->get_user( $request );
    608 
    609 		if ( is_wp_error( $user ) ) {
    610 			return $user;
    611 		}
    612 
    613 		$prepared = array(
    614 			'uuid'      => $item['uuid'],
    615 			'app_id'    => empty( $item['app_id'] ) ? '' : $item['app_id'],
    616 			'name'      => $item['name'],
    617 			'created'   => gmdate( 'Y-m-d\TH:i:s', $item['created'] ),
    618 			'last_used' => $item['last_used'] ? gmdate( 'Y-m-d\TH:i:s', $item['last_used'] ) : null,
    619 			'last_ip'   => $item['last_ip'] ? $item['last_ip'] : null,
    620 		);
    621 
    622 		if ( isset( $item['new_password'] ) ) {
    623 			$prepared['password'] = $item['new_password'];
    624 		}
    625 
    626 		$prepared = $this->add_additional_fields_to_object( $prepared, $request );
    627 		$prepared = $this->filter_response_by_context( $prepared, $request['context'] );
    628 
    629 		$response = new WP_REST_Response( $prepared );
    630 		$response->add_links( $this->prepare_links( $user, $item ) );
    631 
    632 		/**
    633 		 * Filters the REST API response for an application password.
    634 		 *
    635 		 * @since 5.6.0
    636 		 *
    637 		 * @param WP_REST_Response $response The response object.
    638 		 * @param array            $item     The application password array.
    639 		 * @param WP_REST_Request  $request  The request object.
    640 		 */
    641 		return apply_filters( 'rest_prepare_application_password', $response, $item, $request );
    642 	}
    643 
    644 	/**
    645 	 * Prepares links for the request.
    646 	 *
    647 	 * @since 5.6.0
    648 	 *
    649 	 * @param WP_User $user The requested user.
    650 	 * @param array   $item The application password.
    651 	 * @return array The list of links.
    652 	 */
    653 	protected function prepare_links( WP_User $user, $item ) {
    654 		return array(
    655 			'self' => array(
    656 				'href' => rest_url( sprintf( '%s/users/%d/application-passwords/%s', $this->namespace, $user->ID, $item['uuid'] ) ),
    657 			),
    658 		);
    659 	}
    660 
    661 	/**
    662 	 * Gets the requested user.
    663 	 *
    664 	 * @since 5.6.0
    665 	 *
    666 	 * @param WP_REST_Request $request The request object.
    667 	 * @return WP_User|WP_Error The WordPress user associated with the request, or a WP_Error if none found.
    668 	 */
    669 	protected function get_user( $request ) {
    670 		if ( ! wp_is_application_passwords_available() ) {
    671 			return new WP_Error(
    672 				'application_passwords_disabled',
    673 				__( 'Application passwords are not available.' ),
    674 				array( 'status' => 501 )
    675 			);
    676 		}
    677 
    678 		$error = new WP_Error(
    679 			'rest_user_invalid_id',
    680 			__( 'Invalid user ID.' ),
    681 			array( 'status' => 404 )
    682 		);
    683 
    684 		$id = $request['user_id'];
    685 
    686 		if ( 'me' === $id ) {
    687 			if ( ! is_user_logged_in() ) {
    688 				return new WP_Error(
    689 					'rest_not_logged_in',
    690 					__( 'You are not currently logged in.' ),
    691 					array( 'status' => 401 )
    692 				);
    693 			}
    694 
    695 			$user = wp_get_current_user();
    696 		} else {
    697 			$id = (int) $id;
    698 
    699 			if ( $id <= 0 ) {
    700 				return $error;
    701 			}
    702 
    703 			$user = get_userdata( $id );
    704 		}
    705 
    706 		if ( empty( $user ) || ! $user->exists() ) {
    707 			return $error;
    708 		}
    709 
    710 		if ( is_multisite() && ! is_user_member_of_blog( $user->ID ) ) {
    711 			return $error;
    712 		}
    713 
    714 		if ( ! wp_is_application_passwords_available_for_user( $user ) ) {
    715 			return new WP_Error(
    716 				'application_passwords_disabled_for_user',
    717 				__( 'Application passwords are not available for your account. Please contact the site administrator for assistance.' ),
    718 				array( 'status' => 501 )
    719 			);
    720 		}
    721 
    722 		return $user;
    723 	}
    724 
    725 	/**
    726 	 * Gets the requested application password.
    727 	 *
    728 	 * @since 5.6.0
    729 	 *
    730 	 * @param WP_REST_Request $request The request object.
    731 	 * @return array|WP_Error The application password details if found, a WP_Error otherwise.
    732 	 */
    733 	protected function get_application_password( $request ) {
    734 		$user = $this->get_user( $request );
    735 
    736 		if ( is_wp_error( $user ) ) {
    737 			return $user;
    738 		}
    739 
    740 		$password = WP_Application_Passwords::get_user_application_password( $user->ID, $request['uuid'] );
    741 
    742 		if ( ! $password ) {
    743 			return new WP_Error(
    744 				'rest_application_password_not_found',
    745 				__( 'Application password not found.' ),
    746 				array( 'status' => 404 )
    747 			);
    748 		}
    749 
    750 		return $password;
    751 	}
    752 
    753 	/**
    754 	 * Retrieves the query params for the collections.
    755 	 *
    756 	 * @since 5.6.0
    757 	 *
    758 	 * @return array Query parameters for the collection.
    759 	 */
    760 	public function get_collection_params() {
    761 		return array(
    762 			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
    763 		);
    764 	}
    765 
    766 	/**
    767 	 * Retrieves the application password's schema, conforming to JSON Schema.
    768 	 *
    769 	 * @since 5.6.0
    770 	 *
    771 	 * @return array Item schema data.
    772 	 */
    773 	public function get_item_schema() {
    774 		if ( $this->schema ) {
    775 			return $this->add_additional_fields_schema( $this->schema );
    776 		}
    777 
    778 		$this->schema = array(
    779 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
    780 			'title'      => 'application-password',
    781 			'type'       => 'object',
    782 			'properties' => array(
    783 				'uuid'      => array(
    784 					'description' => __( 'The unique identifier for the application password.' ),
    785 					'type'        => 'string',
    786 					'format'      => 'uuid',
    787 					'context'     => array( 'view', 'edit', 'embed' ),
    788 					'readonly'    => true,
    789 				),
    790 				'app_id'    => array(
    791 					'description' => __( 'A uuid provided by the application to uniquely identify it. It is recommended to use an UUID v5 with the URL or DNS namespace.' ),
    792 					'type'        => 'string',
    793 					'format'      => 'uuid',
    794 					'context'     => array( 'view', 'edit', 'embed' ),
    795 				),
    796 				'name'      => array(
    797 					'description' => __( 'The name of the application password.' ),
    798 					'type'        => 'string',
    799 					'required'    => true,
    800 					'context'     => array( 'view', 'edit', 'embed' ),
    801 					'minLength'   => 1,
    802 					'pattern'     => '.*\S.*',
    803 				),
    804 				'password'  => array(
    805 					'description' => __( 'The generated password. Only available after adding an application.' ),
    806 					'type'        => 'string',
    807 					'context'     => array( 'edit' ),
    808 					'readonly'    => true,
    809 				),
    810 				'created'   => array(
    811 					'description' => __( 'The GMT date the application password was created.' ),
    812 					'type'        => 'string',
    813 					'format'      => 'date-time',
    814 					'context'     => array( 'view', 'edit' ),
    815 					'readonly'    => true,
    816 				),
    817 				'last_used' => array(
    818 					'description' => __( 'The GMT date the application password was last used.' ),
    819 					'type'        => array( 'string', 'null' ),
    820 					'format'      => 'date-time',
    821 					'context'     => array( 'view', 'edit' ),
    822 					'readonly'    => true,
    823 				),
    824 				'last_ip'   => array(
    825 					'description' => __( 'The IP address the application password was last used by.' ),
    826 					'type'        => array( 'string', 'null' ),
    827 					'format'      => 'ip',
    828 					'context'     => array( 'view', 'edit' ),
    829 					'readonly'    => true,
    830 				),
    831 			),
    832 		);
    833 
    834 		return $this->add_additional_fields_schema( $this->schema );
    835 	}
    836 }