Fix #17262 - Add warning when setting a password to a blank value if AllowNoPassword is false (#19315)

* Fix #17262 - Add warning when setting a password to a blank value if AllowNoPassword is false

Closes #17262

Signed-off-by: Jacek Barecki <jacek.barecki@gmail.com>
Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
This commit is contained in:
Jacek Barecki 2024-10-11 19:35:11 +02:00 committed by GitHub
parent 720de704f8
commit 003f092277
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 83 additions and 19 deletions

View File

@ -158,7 +158,7 @@ return [
'server_plugins' => ['class' => Plugins::class, 'arguments' => ['@dbi']],
'server_privileges' => [
'class' => Privileges::class,
'arguments' => ['@template', '@dbi', '@relation', '@relation_cleanup', '@server_plugins'],
'arguments' => ['@template', '@dbi', '@relation', '@relation_cleanup', '@server_plugins', '@config'],
],
'server_privileges_account_locking' => [
'class' => AccountLocking::class,

View File

@ -700,6 +700,7 @@ return [
'$relation' => '@relation',
'$dbi' => '@dbi',
'$userPrivilegesFactory' => '@' . UserPrivilegesFactory::class,
'$config' => '@config',
],
],
Server\ReplicationController::class => [

View File

@ -1974,6 +1974,10 @@ export function checkPassword ($theForm) {
return true;
}
export function shouldShowEmptyPasswordWarning (form): boolean {
return (form.find('#nopass_1').is(':checked') && form.data('allowNoPassword') === 0);
}
export function onloadChangePasswordEvents (): void {
/* Handler for hostname type */
$(document).on('change', '#select_pred_hostname', function () {
@ -2067,25 +2071,35 @@ export function onloadChangePasswordEvents (): void {
*/
var thisValue = $(this).val();
var $msgbox = ajaxShowMessage(window.Messages.strProcessingRequest);
$theForm.append('<input type="hidden" name="ajax_request" value="true">');
var submitForm = function () {
var $msgbox = ajaxShowMessage(window.Messages.strProcessingRequest);
$theForm.append('<input type="hidden" name="ajax_request" value="true">');
$.post($theForm.attr('action'), $theForm.serialize() + CommonParams.get('arg_separator') + 'change_pw=' + thisValue, function (data) {
if (typeof data === 'undefined' || data.success !== true) {
ajaxShowMessage(data.error, false);
$.post($theForm.attr('action'), $theForm.serialize() + CommonParams.get('arg_separator') + 'change_pw=' + thisValue, function (data) {
if (typeof data === 'undefined' || data.success !== true) {
ajaxShowMessage(data.error, false);
return;
}
return;
}
var $pageContent = $('#page_content');
$pageContent.prepend(data.message);
highlightSql($pageContent);
$('#change_password_dialog').hide().remove();
$('#edit_user_dialog').dialog('close').remove();
ajaxRemoveMessage($msgbox);
}); // end $.post()
var $pageContent = $('#page_content');
$pageContent.prepend(data.message);
highlightSql($pageContent);
$('#change_password_dialog').hide().remove();
$('#edit_user_dialog').dialog('close').remove();
ajaxRemoveMessage($msgbox);
}); // end $.post()
$('#changePasswordModal').modal('hide');
$('#changePasswordModal').modal('hide');
};
if (shouldShowEmptyPasswordWarning($theForm)) {
$(this).confirm(window.Messages.strPasswordEmptyWhenAllowNoPasswordIsEnabled, '', function () {
submitForm();
});
} else {
submitForm();
}
});
$.get($(this).attr('href'), { 'ajax_request': true }, function (data) {

View File

@ -1,6 +1,13 @@
import $ from 'jquery';
import { AJAX } from '../modules/ajax.ts';
import { checkPassword, checkPasswordStrength, checkboxesSel, displayPasswordGenerateButton, getSqlEditor } from '../modules/functions.ts';
import {
checkPassword,
checkPasswordStrength,
checkboxesSel,
displayPasswordGenerateButton,
getSqlEditor,
shouldShowEmptyPasswordWarning
} from '../modules/functions.ts';
import { CommonParams } from '../modules/common.ts';
import { Navigation } from '../modules/navigation.ts';
import { ajaxRemoveMessage, ajaxShowMessage } from '../modules/ajax-message.ts';
@ -475,6 +482,26 @@ const CheckAddUser = {
}
};
const CheckEmptyPasswordWhenAllowNoPasswordIsEnabled = {
handleEvent: function () {
const theForm = this;
if (shouldShowEmptyPasswordWarning($(theForm))) {
$(this).confirm(window.Messages.strPasswordEmptyWhenAllowNoPasswordIsEnabled, '', function () {
theForm.submit();
return true;
});
return false;
} else {
theForm.submit();
return true;
}
}
};
const selectPasswordRadioWhenChangingPassword = () => {
$('#nopass_0').prop('checked', true);
};
@ -561,4 +588,5 @@ AJAX.registerOnload('server/privileges.js', function () {
$('#addUsersForm').on('submit', CheckAddUser.handleEvent);
$('#copyUserForm').on('submit', CheckAddUser.handleEvent);
$('#change_password_form').on('submit', CheckEmptyPasswordWhenAllowNoPasswordIsEnabled.handleEvent);
});

View File

@ -1,5 +1,5 @@
<form method="post" id="change_password_form" action="
{{- is_privileges ? url('/server/privileges') : url('/user-password') }}" name="chgPassword" class="{{ is_privileges ? 'submenu-item' }}" autocomplete="off">
{{- is_privileges ? url('/server/privileges') : url('/user-password') }}" name="chgPassword" class="{{ is_privileges ? 'submenu-item' }}" autocomplete="off" data-allow-no-password="{{ allow_no_password ? 1 : 0 }}">
{{ get_hidden_inputs() }}
{% if is_privileges %}
<input type="hidden" name="username" value="{{ username }}">

View File

@ -143,6 +143,11 @@ final class JavaScriptMessagesController implements InvocableController
'strUserEmpty' => __('The user name is empty!'),
'strPasswordEmpty' => __('The password is empty!'),
'strPasswordNotSame' => __('The passwords aren\'t the same!'),
'strPasswordEmptyWhenAllowNoPasswordIsEnabled' => __(
'You are trying to set this account to log in with no password, but the configuration directive ' .
'<code>AllowNoPassword</code> is false. If you proceed, the account will not be able to log in ' .
'through phpMyAdmin.',
),
'strRemovingSelectedUsers' => __('Removing Selected Users'),
'strClose' => __('Close'),
'strLock' => _pgettext('Lock the account.', 'Lock'),

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Controllers\Server;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\ConfigStorage\RelationCleanup;
use PhpMyAdmin\Controllers\InvocableController;
@ -38,6 +39,7 @@ final class PrivilegesController implements InvocableController
private readonly Relation $relation,
private readonly DatabaseInterface $dbi,
private readonly UserPrivilegesFactory $userPrivilegesFactory,
private readonly Config $config,
) {
}
@ -62,6 +64,7 @@ final class PrivilegesController implements InvocableController
$this->relation,
$relationCleanup,
new Plugins($this->dbi),
$this->config,
);
$this->response->addHTML('<div class="container-fluid">');

View File

@ -76,6 +76,7 @@ class Privileges
public Relation $relation,
private RelationCleanup $relationCleanup,
private Plugins $plugins,
private readonly Config $config,
) {
}
@ -3270,6 +3271,7 @@ class Privileges
'has_more_auth_plugins' => $hasMoreAuthPlugins,
'active_auth_plugins' => $activeAuthPlugins,
'orig_auth_plugin' => $origAuthPlugin,
'allow_no_password' => $this->config->selectedServer['AllowNoPassword'],
]);
}

View File

@ -75,6 +75,7 @@ class PrivilegesControllerTest extends AbstractTestCase
new Relation($this->dbi),
$this->dbi,
new UserPrivilegesFactory($this->dbi),
new Config(),
))($request);
$actual = $response->getHTMLResult();

View File

@ -1889,6 +1889,7 @@ class PrivilegesTest extends AbstractTestCase
$relation,
new RelationCleanup($this->dbi, $relation),
new Plugins($this->dbi),
new Config(),
);
$method = new ReflectionMethod(Privileges::class, 'getUserPrivileges');
@ -1902,7 +1903,14 @@ class PrivilegesTest extends AbstractTestCase
{
$relation = new Relation($dbi);
return new Privileges(new Template(), $dbi, $relation, new RelationCleanup($dbi, $relation), new Plugins($dbi));
return new Privileges(
new Template(),
$dbi,
$relation,
new RelationCleanup($dbi, $relation),
new Plugins($dbi),
new Config(),
);
}
/**

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\ConfigStorage\RelationCleanup;
use PhpMyAdmin\Message;
@ -35,6 +36,7 @@ class UserPasswordTest extends AbstractTestCase
$relation,
new RelationCleanup($dbi, $relation),
new Plugins($dbi),
new Config(),
);
$this->object = new UserPassword(
$serverPrivileges,