Skip to content

Commit 5817f59

Browse files
authored
Merge pull request #1719 from IrAlfred/enh-password-update-to-preserve-settings
feat(other): preserve user settings during password update
2 parents c7903a3 + d4da34e commit 5817f59

File tree

1 file changed

+104
-11
lines changed

1 file changed

+104
-11
lines changed

scripts/update_password.php

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,38 @@
22

33
/**
44
* CLI script to update a user password
5+
*
6+
* Usage:
7+
* - With old password (preserves user data): php ./scripts/update_password.php <username> <old_password> <new_password>
8+
* - Without old password (data loss warning): php ./scripts/update_password.php <username> <new_password>
59
*/
610
if (mb_strtolower(php_sapi_name()) !== 'cli') {
711
die("Must be run from the command line\n");
812
}
913

10-
if (is_array($argv) && count($argv) == 3) {
11-
$user = $argv[1];
12-
$pass = $argv[2];
13-
}
14-
else {
15-
die("Incorrect usage\n\nphp ./scripts/update_password.php <username> <password>\n\n");
14+
$user = '';
15+
$old_pass = '';
16+
$new_pass = '';
17+
$incorrect_usage_msg = "Incorrect usage\n\nUsage:\n" .
18+
" With old password (preserves user config and needs [sudo]):\n php ./scripts/update_password.php <username> <old_password> <new_password>\n\n" .
19+
" Without old password (user config will be lost):\n php ./scripts/update_password.php <username> <new_password>\n\n";
20+
21+
if (is_array($argv)) {
22+
if (count($argv) == 4) {
23+
// Mode 1: With old password
24+
$user = $argv[1];
25+
$old_pass = $argv[2];
26+
$new_pass = $argv[3];
27+
$preserve_data = true;
28+
} elseif (count($argv) == 3) {
29+
$user = $argv[1];
30+
$new_pass = $argv[2];
31+
$preserve_data = false;
32+
} else {
33+
die($incorrect_usage_msg);
34+
}
35+
} else {
36+
die($incorrect_usage_msg);
1637
}
1738

1839
/* debug mode has to be set to something or include files will die() */
@@ -40,11 +61,83 @@
4061
}
4162

4263
$auth = new Hm_Auth_DB($config);
43-
if ($user && $pass) {
44-
if ($auth->change_pass($user, $pass)) {
45-
die("Password Updated\n\n");
64+
65+
/**
66+
* Get user confirmation from stdin
67+
*
68+
* @param string $message Message to display to the user
69+
* @return bool True if user provides a valid confirmation, false otherwise
70+
*/
71+
function get_user_confirmation($message) {
72+
echo $message;
73+
$handle = fopen("php://stdin", "r");
74+
$input = strtolower(trim(fgets($handle)));
75+
fclose($handle);
76+
77+
return in_array($input, ['y', 'yes']);
78+
}
79+
80+
/**
81+
* Change user password with error handling
82+
*
83+
* @param Hm_Auth_DB $auth Authentication object
84+
* @param string $user Username
85+
* @param string $new_pass New password
86+
* @return void Dies on failure
87+
*/
88+
function change_password_or_die($auth, $user, $new_pass) {
89+
if (!$auth->change_pass($user, $new_pass)) {
90+
die("Error: Failed to update password\n\n");
91+
}
92+
}
93+
94+
if ($preserve_data) {
95+
if (! $auth->check_credentials($user, $old_pass)) {
96+
die("Invalid username or password provided\n\n");
97+
}
98+
$user_config = load_user_config_object($config);
99+
$user_config->load($user, $old_pass);
100+
$load_success = ! $user_config->decrypt_failed;
101+
if ($load_success) {
102+
$config_data = $user_config->dump();
103+
104+
change_password_or_die($auth, $user, $new_pass);
105+
try {
106+
$user_config->save($user, $new_pass);
107+
echo "Password updated successfully.\n\n";
108+
} catch (Exception $e) {
109+
echo "Error: Could not save user configuration: " . $e->getMessage() . "\n";
110+
echo "Reverting password change...\n";
111+
if ($auth->change_pass($user, $old_pass)) {
112+
die("Password change reverted successfully.\n\n");
113+
} else {
114+
die("CRITICAL ERROR: Password was changed but could not be reverted! You need to revert it manually.\n\n");
115+
}
116+
}
117+
118+
} else {
119+
$confirm = get_user_confirmation(
120+
"Warning: Could not decrypt existing user configuration with provided old password.\n" .
121+
"User data may not be preserved. Continue? (y/N): "
122+
);
123+
124+
if (!$confirm) {
125+
die("Password update cancelled.\n\n");
126+
} else {
127+
change_password_or_die($auth, $user, $new_pass);
128+
echo "Password updated successfully !\n\n";
129+
}
46130
}
47-
else {
48-
die("An error occured\n\n");
131+
} else {
132+
$confirm = get_user_confirmation(
133+
"Not providing old password will result in LOSS OF ALL USER CONFIGURATION DATA!\n" .
134+
"Are you sure you want to continue? Type 'y' or 'yes' to confirm: "
135+
);
136+
137+
if (!$confirm) {
138+
die("Password update cancelled.\n\n");
49139
}
140+
141+
change_password_or_die($auth, $user, $new_pass);
142+
echo "Password updated successfully.\n";
50143
}

0 commit comments

Comments
 (0)