[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * WP_Application_Passwords class 4 * 5 * @package WordPress 6 * @since 5.6.0 7 */ 8 9 /** 10 * Class for displaying, modifying, and sanitizing application passwords. 11 * 12 * @package WordPress 13 */ 14 #[AllowDynamicProperties] 15 class WP_Application_Passwords { 16 17 /** 18 * The application passwords user meta key. 19 * 20 * @since 5.6.0 21 * 22 * @var string 23 */ 24 const USERMETA_KEY_APPLICATION_PASSWORDS = '_application_passwords'; 25 26 /** 27 * The option name used to store whether application passwords are in use. 28 * 29 * @since 5.6.0 30 * 31 * @var string 32 */ 33 const OPTION_KEY_IN_USE = 'using_application_passwords'; 34 35 /** 36 * The generated application password length. 37 * 38 * @since 5.6.0 39 * 40 * @var int 41 */ 42 const PW_LENGTH = 24; 43 44 /** 45 * Checks if application passwords are being used by the site. 46 * 47 * This returns true if at least one application password has ever been created. 48 * 49 * @since 5.6.0 50 * 51 * @return bool 52 */ 53 public static function is_in_use() { 54 $network_id = get_main_network_id(); 55 return (bool) get_network_option( $network_id, self::OPTION_KEY_IN_USE ); 56 } 57 58 /** 59 * Creates a new application password. 60 * 61 * @since 5.6.0 62 * @since 5.7.0 Returns WP_Error if application name already exists. 63 * 64 * @param int $user_id User ID. 65 * @param array $args { 66 * Arguments used to create the application password. 67 * 68 * @type string $name The name of the application password. 69 * @type string $app_id A UUID provided by the application to uniquely identify it. 70 * } 71 * @return array|WP_Error { 72 * Application password details, or a WP_Error instance if an error occurs. 73 * 74 * @type string $0 The unhashed generated application password. 75 * @type array $1 { 76 * The details about the created password. 77 * 78 * @type string $uuid The unique identifier for the application password. 79 * @type string $app_id A UUID provided by the application to uniquely identify it. 80 * @type string $name The name of the application password. 81 * @type string $password A one-way hash of the password. 82 * @type int $created Unix timestamp of when the password was created. 83 * @type null $last_used Null. 84 * @type null $last_ip Null. 85 * } 86 * } 87 */ 88 public static function create_new_application_password( $user_id, $args = array() ) { 89 if ( ! empty( $args['name'] ) ) { 90 $args['name'] = sanitize_text_field( $args['name'] ); 91 } 92 93 if ( empty( $args['name'] ) ) { 94 return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) ); 95 } 96 97 if ( self::application_name_exists_for_user( $user_id, $args['name'] ) ) { 98 return new WP_Error( 'application_password_duplicate_name', __( 'Each application name should be unique.' ), array( 'status' => 409 ) ); 99 } 100 101 $new_password = wp_generate_password( static::PW_LENGTH, false ); 102 $hashed_password = wp_hash_password( $new_password ); 103 104 $new_item = array( 105 'uuid' => wp_generate_uuid4(), 106 'app_id' => empty( $args['app_id'] ) ? '' : $args['app_id'], 107 'name' => $args['name'], 108 'password' => $hashed_password, 109 'created' => time(), 110 'last_used' => null, 111 'last_ip' => null, 112 ); 113 114 $passwords = static::get_user_application_passwords( $user_id ); 115 $passwords[] = $new_item; 116 $saved = static::set_user_application_passwords( $user_id, $passwords ); 117 118 if ( ! $saved ) { 119 return new WP_Error( 'db_error', __( 'Could not save application password.' ) ); 120 } 121 122 $network_id = get_main_network_id(); 123 if ( ! get_network_option( $network_id, self::OPTION_KEY_IN_USE ) ) { 124 update_network_option( $network_id, self::OPTION_KEY_IN_USE, true ); 125 } 126 127 /** 128 * Fires when an application password is created. 129 * 130 * @since 5.6.0 131 * 132 * @param int $user_id The user ID. 133 * @param array $new_item { 134 * The details about the created password. 135 * 136 * @type string $uuid The unique identifier for the application password. 137 * @type string $app_id A UUID provided by the application to uniquely identify it. 138 * @type string $name The name of the application password. 139 * @type string $password A one-way hash of the password. 140 * @type int $created Unix timestamp of when the password was created. 141 * @type null $last_used Null. 142 * @type null $last_ip Null. 143 * } 144 * @param string $new_password The unhashed generated application password. 145 * @param array $args { 146 * Arguments used to create the application password. 147 * 148 * @type string $name The name of the application password. 149 * @type string $app_id A UUID provided by the application to uniquely identify it. 150 * } 151 */ 152 do_action( 'wp_create_application_password', $user_id, $new_item, $new_password, $args ); 153 154 return array( $new_password, $new_item ); 155 } 156 157 /** 158 * Gets a user's application passwords. 159 * 160 * @since 5.6.0 161 * 162 * @param int $user_id User ID. 163 * @return array { 164 * The list of app passwords. 165 * 166 * @type array ...$0 { 167 * @type string $uuid The unique identifier for the application password. 168 * @type string $app_id A UUID provided by the application to uniquely identify it. 169 * @type string $name The name of the application password. 170 * @type string $password A one-way hash of the password. 171 * @type int $created Unix timestamp of when the password was created. 172 * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used. 173 * @type string|null $last_ip The IP address the application password was last used by. 174 * } 175 * } 176 */ 177 public static function get_user_application_passwords( $user_id ) { 178 $passwords = get_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, true ); 179 180 if ( ! is_array( $passwords ) ) { 181 return array(); 182 } 183 184 $save = false; 185 186 foreach ( $passwords as $i => $password ) { 187 if ( ! isset( $password['uuid'] ) ) { 188 $passwords[ $i ]['uuid'] = wp_generate_uuid4(); 189 $save = true; 190 } 191 } 192 193 if ( $save ) { 194 static::set_user_application_passwords( $user_id, $passwords ); 195 } 196 197 return $passwords; 198 } 199 200 /** 201 * Gets a user's application password with the given UUID. 202 * 203 * @since 5.6.0 204 * 205 * @param int $user_id User ID. 206 * @param string $uuid The password's UUID. 207 * @return array|null The application password if found, null otherwise. 208 */ 209 public static function get_user_application_password( $user_id, $uuid ) { 210 $passwords = static::get_user_application_passwords( $user_id ); 211 212 foreach ( $passwords as $password ) { 213 if ( $password['uuid'] === $uuid ) { 214 return $password; 215 } 216 } 217 218 return null; 219 } 220 221 /** 222 * Checks if an application password with the given name exists for this user. 223 * 224 * @since 5.7.0 225 * 226 * @param int $user_id User ID. 227 * @param string $name Application name. 228 * @return bool Whether the provided application name exists. 229 */ 230 public static function application_name_exists_for_user( $user_id, $name ) { 231 $passwords = static::get_user_application_passwords( $user_id ); 232 233 foreach ( $passwords as $password ) { 234 if ( strtolower( $password['name'] ) === strtolower( $name ) ) { 235 return true; 236 } 237 } 238 239 return false; 240 } 241 242 /** 243 * Updates an application password. 244 * 245 * @since 5.6.0 246 * 247 * @param int $user_id User ID. 248 * @param string $uuid The password's UUID. 249 * @param array $update Information about the application password to update. 250 * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error. 251 */ 252 public static function update_application_password( $user_id, $uuid, $update = array() ) { 253 $passwords = static::get_user_application_passwords( $user_id ); 254 255 foreach ( $passwords as &$item ) { 256 if ( $item['uuid'] !== $uuid ) { 257 continue; 258 } 259 260 if ( ! empty( $update['name'] ) ) { 261 $update['name'] = sanitize_text_field( $update['name'] ); 262 } 263 264 $save = false; 265 266 if ( ! empty( $update['name'] ) && $item['name'] !== $update['name'] ) { 267 $item['name'] = $update['name']; 268 $save = true; 269 } 270 271 if ( $save ) { 272 $saved = static::set_user_application_passwords( $user_id, $passwords ); 273 274 if ( ! $saved ) { 275 return new WP_Error( 'db_error', __( 'Could not save application password.' ) ); 276 } 277 } 278 279 /** 280 * Fires when an application password is updated. 281 * 282 * @since 5.6.0 283 * 284 * @param int $user_id The user ID. 285 * @param array $item The updated app password details. 286 * @param array $update The information to update. 287 */ 288 do_action( 'wp_update_application_password', $user_id, $item, $update ); 289 290 return true; 291 } 292 293 return new WP_Error( 'application_password_not_found', __( 'Could not find an application password with that id.' ) ); 294 } 295 296 /** 297 * Records that an application password has been used. 298 * 299 * @since 5.6.0 300 * 301 * @param int $user_id User ID. 302 * @param string $uuid The password's UUID. 303 * @return true|WP_Error True if the usage was recorded, a WP_Error if an error occurs. 304 */ 305 public static function record_application_password_usage( $user_id, $uuid ) { 306 $passwords = static::get_user_application_passwords( $user_id ); 307 308 foreach ( $passwords as &$password ) { 309 if ( $password['uuid'] !== $uuid ) { 310 continue; 311 } 312 313 // Only record activity once a day. 314 if ( $password['last_used'] + DAY_IN_SECONDS > time() ) { 315 return true; 316 } 317 318 $password['last_used'] = time(); 319 $password['last_ip'] = $_SERVER['REMOTE_ADDR']; 320 321 $saved = static::set_user_application_passwords( $user_id, $passwords ); 322 323 if ( ! $saved ) { 324 return new WP_Error( 'db_error', __( 'Could not save application password.' ) ); 325 } 326 327 return true; 328 } 329 330 // Specified application password not found! 331 return new WP_Error( 'application_password_not_found', __( 'Could not find an application password with that id.' ) ); 332 } 333 334 /** 335 * Deletes an application password. 336 * 337 * @since 5.6.0 338 * 339 * @param int $user_id User ID. 340 * @param string $uuid The password's UUID. 341 * @return true|WP_Error Whether the password was successfully found and deleted, a WP_Error otherwise. 342 */ 343 public static function delete_application_password( $user_id, $uuid ) { 344 $passwords = static::get_user_application_passwords( $user_id ); 345 346 foreach ( $passwords as $key => $item ) { 347 if ( $item['uuid'] === $uuid ) { 348 unset( $passwords[ $key ] ); 349 $saved = static::set_user_application_passwords( $user_id, $passwords ); 350 351 if ( ! $saved ) { 352 return new WP_Error( 'db_error', __( 'Could not delete application password.' ) ); 353 } 354 355 /** 356 * Fires when an application password is deleted. 357 * 358 * @since 5.6.0 359 * 360 * @param int $user_id The user ID. 361 * @param array $item The data about the application password. 362 */ 363 do_action( 'wp_delete_application_password', $user_id, $item ); 364 365 return true; 366 } 367 } 368 369 return new WP_Error( 'application_password_not_found', __( 'Could not find an application password with that id.' ) ); 370 } 371 372 /** 373 * Deletes all application passwords for the given user. 374 * 375 * @since 5.6.0 376 * 377 * @param int $user_id User ID. 378 * @return int|WP_Error The number of passwords that were deleted or a WP_Error on failure. 379 */ 380 public static function delete_all_application_passwords( $user_id ) { 381 $passwords = static::get_user_application_passwords( $user_id ); 382 383 if ( $passwords ) { 384 $saved = static::set_user_application_passwords( $user_id, array() ); 385 386 if ( ! $saved ) { 387 return new WP_Error( 'db_error', __( 'Could not delete application passwords.' ) ); 388 } 389 390 foreach ( $passwords as $item ) { 391 /** This action is documented in wp-includes/class-wp-application-passwords.php */ 392 do_action( 'wp_delete_application_password', $user_id, $item ); 393 } 394 395 return count( $passwords ); 396 } 397 398 return 0; 399 } 400 401 /** 402 * Sets a user's application passwords. 403 * 404 * @since 5.6.0 405 * 406 * @param int $user_id User ID. 407 * @param array $passwords Application passwords. 408 * 409 * @return bool 410 */ 411 protected static function set_user_application_passwords( $user_id, $passwords ) { 412 return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords ); 413 } 414 415 /** 416 * Sanitizes and then splits a password into smaller chunks. 417 * 418 * @since 5.6.0 419 * 420 * @param string $raw_password The raw application password. 421 * @return string The chunked password. 422 */ 423 public static function chunk_password( $raw_password ) { 424 $raw_password = preg_replace( '/[^a-z\d]/i', '', $raw_password ); 425 426 return trim( chunk_split( $raw_password, 4, ' ' ) ); 427 } 428 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Wed Apr 24 08:20:01 2024 | Cross-referenced by PHPXref |