<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[50030] trunk: App Passwords: Improve validation and sanitization of the application name.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/50030">50030</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/50030","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>TimothyBlynJacobs</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2021-01-27 19:03:42 +0000 (Wed, 27 Jan 2021)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>App Passwords: Improve validation and sanitization of the application name.

Application names are now required to be unique and cannot contain solely whitespace characters. Additionally, invalid characters are now stripped from the application name using `sanitize_text_field()`.

Props Boniu91, hellofromTonya, engahmeds3ed, xkon, francina.
Fixes <a href="https://core.trac.wordpress.org/ticket/51941">#51941</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcjs_enqueuesadminapplicationpasswordsjs">trunk/src/js/_enqueues/admin/application-passwords.js</a></li>
<li><a href="#trunksrcjs_enqueuesadminauthappjs">trunk/src/js/_enqueues/admin/auth-app.js</a></li>
<li><a href="#trunksrcwpincludesclasswpapplicationpasswordsphp">trunk/src/wp-includes/class-wp-application-passwords.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestapplicationpasswordscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestapplicationpasswordscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php</a></li>
<li><a href="#trunktestsqunitfixtureswpapigeneratedjs">trunk/tests/qunit/fixtures/wp-api-generated.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsrestapiapplicationpasswordsphp">trunk/tests/phpunit/tests/rest-api/application-passwords.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcjs_enqueuesadminapplicationpasswordsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/js/_enqueues/admin/application-passwords.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/js/_enqueues/admin/application-passwords.js     2021-01-27 14:49:56 UTC (rev 50029)
+++ trunk/src/js/_enqueues/admin/application-passwords.js       2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -57,7 +57,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $newAppPassButton.prop( 'disabled', false );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $newAppPassForm.after( tmplNewAppPass( {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                name: name,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         name: response.name,
</ins><span class="cx" style="display: block; padding: 0 10px">                                 password: response.password
</span><span class="cx" style="display: block; padding: 0 10px">                        } ) );
</span><span class="cx" style="display: block; padding: 0 10px">                        $( '.new-application-password-notice' ).focus();
</span></span></pre></div>
<a id="trunksrcjs_enqueuesadminauthappjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/js/_enqueues/admin/auth-app.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/js/_enqueues/admin/auth-app.js  2021-01-27 14:49:56 UTC (rev 50029)
+++ trunk/src/js/_enqueues/admin/auth-app.js    2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -98,7 +98,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        .append( '<p>' + wp.i18n.__( 'Be sure to save this in a safe location. You will not be able to retrieve it.' ) + '</p>' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // We're using .text() to write the variables to avoid any chance of XSS.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $( 'strong', $notice ).text( name );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $( 'strong', $notice ).text( response.name );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $( 'input', $notice ).val( response.password );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $form.replaceWith( $notice );
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpapplicationpasswordsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-application-passwords.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-application-passwords.php  2021-01-27 14:49:56 UTC (rev 50029)
+++ trunk/src/wp-includes/class-wp-application-passwords.php    2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -58,6 +58,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Creates a new application password.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.6.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 5.7.0 Returns WP_Error if application name already exists.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param int   $user_id  User ID.
</span><span class="cx" style="display: block; padding: 0 10px">         * @param array $args     Information about the application password.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -65,10 +66,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *                        A WP_Error instance is returned on error.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public static function create_new_application_password( $user_id, $args = array() ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( ! empty( $args['name'] ) ) {
+                       $args['name'] = sanitize_text_field( $args['name'] );
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( empty( $args['name'] ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( self::application_name_exists_for_user( $user_id, $args['name'] ) ) {
+                       return new WP_Error( 'application_password_duplicate_name', __( 'Each application name should be unique.' ), array( 'status' => 409 ) );
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $new_password    = wp_generate_password( static::PW_LENGTH, false );
</span><span class="cx" style="display: block; padding: 0 10px">                $hashed_password = wp_hash_password( $new_password );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -163,6 +172,28 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Check if application name exists before for this user.
+        *
+        * @since 5.7.0
+        *
+        * @param int    $user_id User ID.
+        * @param string $name    Application name.
+        *
+        * @return bool Provided application name exists or not.
+        */
+       public static function application_name_exists_for_user( $user_id, $name ) {
+               $passwords = static::get_user_application_passwords( $user_id );
+
+               foreach ( $passwords as $password ) {
+                       if ( strtolower( $password['name'] ) === strtolower( $name ) ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Updates an application password.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.6.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -180,6 +211,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                continue;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        if ( ! empty( $update['name'] ) ) {
+                               $update['name'] = sanitize_text_field( $update['name'] );
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         $save = false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! empty( $update['name'] ) && $item['name'] !== $update['name'] ) {
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestapplicationpasswordscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php       2021-01-27 14:49:56 UTC (rev 50029)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php 2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -631,6 +631,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        'type'        => 'string',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'required'    => true,
</span><span class="cx" style="display: block; padding: 0 10px">                                        'context'     => array( 'view', 'edit', 'embed' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        'minLength'   => 1,
+                                       'pattern'     => '.*\S.*',
</ins><span class="cx" style="display: block; padding: 0 10px">                                 ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'password'  => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                        'description' => __( 'The generated password. Only available after adding an application.' ),
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiapplicationpasswordsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/rest-api/application-passwords.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/application-passwords.php                              (rev 0)
+++ trunk/tests/phpunit/tests/rest-api/application-passwords.php        2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,201 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Unit tests covering WP_Application_Passwords functionality.
+ *
+ * @package    WordPress
+ * @subpackage REST API
+ */
+
+/**
+ * @group  restapi
+ * @group  app_password
+ */
+class Test_WP_Application_Passwords extends WP_UnitTestCase {
+
+       /**
+        * Administrator user id.
+        *
+        * @var int
+        */
+       private static $user_id;
+
+       public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+               self::$user_id = $factory->user->create(
+                       array(
+                               'role' => 'administrator',
+                       )
+               );
+
+               if ( is_multisite() ) {
+                       grant_super_admin( self::$user_id );
+               }
+       }
+
+
+       /**
+        * @covers       WP_Application_Passwords::create_new_application_password
+        * @ticket       51941
+        * @dataProvider data_create_new_application_password_validation
+        */
+       public function test_create_new_application_password_validation( $expected, array $args = array(), array $names = array() ) {
+               // Create the existing passwords.
+               foreach ( $names as $name ) {
+                       WP_Application_Passwords::create_new_application_password( self::$user_id, array( 'name' => $name ) );
+               }
+
+               $actual = WP_Application_Passwords::create_new_application_password( self::$user_id, $args );
+
+               $this->assertInstanceOf( WP_Error::class, $actual );
+               $this->assertSame( $expected['error_code'], $actual->get_error_code() );
+               $this->assertSame( $expected['error_message'], $actual->get_error_message( $expected['error_code'] ) );
+       }
+
+       public function data_create_new_application_password_validation() {
+               return array(
+                       'application_password_empty_name when no args' => array(
+                               'expected' => array(
+                                       'error_code'    => 'application_password_empty_name',
+                                       'error_message' => 'An application name is required to create an application password.',
+                               ),
+                       ),
+                       'application_password_empty_name when no name' => array(
+                               'expected' => array(
+                                       'error_code'    => 'application_password_empty_name',
+                                       'error_message' => 'An application name is required to create an application password.',
+                               ),
+                               'args'     => array( 'app_id' => 1 ),
+                       ),
+                       'application_password_empty_name when empty name' => array(
+                               'expected' => array(
+                                       'error_code'    => 'application_password_empty_name',
+                                       'error_message' => 'An application name is required to create an application password.',
+                               ),
+                               'args'     => array( 'name' => '   ' ),
+                       ),
+                       'application_password_empty_name when <script>' => array(
+                               'expected' => array(
+                                       'error_code'    => 'application_password_empty_name',
+                                       'error_message' => 'An application name is required to create an application password.',
+                               ),
+                               'args'     => array( 'name' => '<script>console.log("Hello")</script>' ),
+                       ),
+                       'application_password_duplicate_name when name exists' => array(
+                               'expected' => array(
+                                       'error_code'    => 'application_password_duplicate_name',
+                                       'error_message' => 'Each application name should be unique.',
+                               ),
+                               'args'     => array( 'name' => 'test2' ),
+                               'names'    => array( 'test1', 'test2' ),
+                       ),
+               );
+       }
+
+       /**
+        * @covers       WP_Application_Passwords::create_new_application_password
+        * @ticket       51941
+        * @dataProvider data_create_new_application_password
+        */
+       public function test_create_new_application_password( array $args, array $names = array() ) {
+               // Create the existing passwords.
+               foreach ( $names as $name ) {
+                       WP_Application_Passwords::create_new_application_password( self::$user_id, array( 'name' => $name ) );
+               }
+
+               list( $new_password, $new_item ) = WP_Application_Passwords::create_new_application_password( self::$user_id, $args );
+
+               $this->assertNotEmpty( $new_password );
+               $this->assertSame(
+                       array( 'uuid', 'app_id', 'name', 'password', 'created', 'last_used', 'last_ip' ),
+                       array_keys( $new_item )
+               );
+               $this->assertSame( $args['name'], $new_item['name'] );
+       }
+
+       public function data_create_new_application_password() {
+               return array(
+                       'should create new password when no passwords exists' => array(
+                               'args' => array( 'name' => 'test3' ),
+                       ),
+                       'should create new password when name is unique'      => array(
+                               'args'  => array( 'name' => 'test3' ),
+                               'names' => array( 'test1', 'test2' ),
+                       ),
+               );
+       }
+
+       /**
+        * @covers       WP_Application_Passwords::application_name_exists_for_user
+        * @ticket       51941
+        * @dataProvider data_application_name_exists_for_user
+        */
+       public function test_application_name_exists_for_user( $expected, $name ) {
+               if ( $expected ) {
+                       WP_Application_Passwords::create_new_application_password( self::$user_id, array( 'name' => $name ) );
+               }
+
+               $this->assertSame( $expected, WP_Application_Passwords::application_name_exists_for_user( self::$user_id, $name ) );
+       }
+
+       public function data_application_name_exists_for_user() {
+               return array(
+                       array( false, 'test1' ),
+                       array( false, 'baz' ),
+                       array( false, 'bar' ),
+                       array( true, 'App 1' ),
+                       array( true, 'Some Test' ),
+                       array( true, 'Baz' ),
+               );
+       }
+
+       /**
+        * @covers       WP_Application_Passwords::update_application_password
+        * @ticket       51941
+        * @dataProvider data_update_application_password
+        */
+       public function test_update_application_password( array $update, array $existing ) {
+               // Create the original item.
+               list( , $original_item ) = WP_Application_Passwords::create_new_application_password( self::$user_id, $existing );
+               $uuid                    = $original_item['uuid'];
+
+               $actual = WP_Application_Passwords::update_application_password( self::$user_id, $uuid, $update );
+
+               $this->assertTrue( $actual );
+
+               // Check updated only given values.
+               $updated_item = WP_Application_Passwords::get_user_application_password( self::$user_id, $uuid );
+               foreach ( $updated_item as $key => $update_value ) {
+                       $expected_value = isset( $update[ $key ] ) ? $update[ $key ] : $original_item[ $key ];
+                       $this->assertSame( $expected_value, $update_value );
+               }
+       }
+
+       /**
+        * @covers       WP_Application_Passwords::update_application_password
+        * @ticket       51941
+        * @dataProvider data_update_application_password
+        */
+       public function test_update_application_password_when_no_password_found( array $update ) {
+               $actual = WP_Application_Passwords::update_application_password( self::$user_id, '', $update );
+
+               $this->assertInstanceOf( WP_Error::class, $actual );
+               $this->assertSame( 'application_password_not_found', $actual->get_error_code() );
+               $this->assertSame( 'Could not find an application password with that id.', $actual->get_error_message( 'application_password_not_found' ) );
+       }
+
+       public function data_update_application_password() {
+               return array(
+                       'should not update when no values given to update' => array(
+                               'update'   => array(),
+                               'existing' => array( 'name' => 'Test' ),
+                       ),
+                       'should not update when given same name' => array(
+                               'update'   => array( 'name' => 'Test' ),
+                               'existing' => array( 'name' => 'Test' ),
+                       ),
+                       'should update name'                     => array(
+                               'update'   => array( 'name' => 'Test Updated' ),
+                               'existing' => array( 'name' => 'Test' ),
+                       ),
+               );
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/rest-api/application-passwords.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsrestapirestapplicationpasswordscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php      2021-01-27 14:49:56 UTC (rev 50029)
+++ trunk/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php        2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -538,6 +538,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">         * @ticket 51583
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @ticket 51941
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><span class="cx" style="display: block; padding: 0 10px">        public function test_update_item_cannot_overwrite_app_id() {
</span><span class="cx" style="display: block; padding: 0 10px">                wp_set_current_user( self::$admin );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -554,7 +555,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                list( , $item ) = WP_Application_Passwords::create_new_application_password(
</span><span class="cx" style="display: block; padding: 0 10px">                        self::$admin,
</span><span class="cx" style="display: block; padding: 0 10px">                        array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                'name'   => 'App',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         'name'   => 'App 2',
</ins><span class="cx" style="display: block; padding: 0 10px">                                 'app_id' => $app_id,
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span></span></pre></div>
<a id="trunktestsqunitfixtureswpapigeneratedjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/qunit/fixtures/wp-api-generated.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/qunit/fixtures/wp-api-generated.js    2021-01-27 14:49:56 UTC (rev 50029)
+++ trunk/tests/qunit/fixtures/wp-api-generated.js      2021-01-27 19:03:42 UTC (rev 50030)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4974,6 +4974,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                         "name": {
</span><span class="cx" style="display: block; padding: 0 10px">                             "description": "The name of the application password.",
</span><span class="cx" style="display: block; padding: 0 10px">                             "type": "string",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                            "minLength": 1,
+                            "pattern": ".*\\S.*",
</ins><span class="cx" style="display: block; padding: 0 10px">                             "required": true
</span><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                     }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5030,6 +5032,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                         "name": {
</span><span class="cx" style="display: block; padding: 0 10px">                             "description": "The name of the application password.",
</span><span class="cx" style="display: block; padding: 0 10px">                             "type": "string",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                            "minLength": 1,
+                            "pattern": ".*\\S.*",
</ins><span class="cx" style="display: block; padding: 0 10px">                             "required": false
</span><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                     }
</span></span></pre>
</div>
</div>

</body>
</html>