Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
89.19% |
66 / 74 |
|
0.00% |
0 / 2 |
CRAP | n/a |
0 / 0 |
|
| check_user_mail | |
62.50% |
10 / 16 |
|
0.00% |
0 / 1 |
11.38 | |||
| inform_to_user | |
96.77% |
30 / 31 |
|
0.00% |
0 / 1 |
3 | |||
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * @file |
| 5 | * Login action: request password recovery (sends recovery email). |
| 6 | * Logic inlined from legacy/login/recover.php; no longer requires that file. |
| 7 | */ |
| 8 | |
| 9 | declare(strict_types=1); |
| 10 | |
| 11 | require_once __DIR__.'/../../Legacy/mailing/mailing.php'; |
| 12 | |
| 13 | /** Path to legacy login html templates (recover, etc.). */ |
| 14 | define('RECOVER_HTML_DIR', __DIR__.'/../legacy/login/html/recover'); |
| 15 | |
| 16 | /** |
| 17 | * Checks that the email exists as USER or STAFF; normalizes $usermail to user email. |
| 18 | * |
| 19 | * Uses central DB (USER, STAFF tables); connection resolved inside. |
| 20 | * |
| 21 | * @param \ConxHelper $conx Connection helper. |
| 22 | * @param string $usermail Email to check (by reference: may be set to user email if staff). |
| 23 | * @param \Psr\Log\LoggerInterface $logger Logger for errors. |
| 24 | * @return bool True if a valid user/staff was found. |
| 25 | */ |
| 26 | function check_user_mail(\ConxHelper $conx, string &$usermail, \Psr\Log\LoggerInterface $logger): bool { |
| 27 | if ($conx->global === null) { |
| 28 | addlog(__FILE__, LogLevel::Error, "Connection to central database failed."); |
| 29 | return false; |
| 30 | } |
| 31 | $results = []; |
| 32 | $res = $conx->global->query('USER', ['email' => $usermail, 'status' => ['PA', 'AC']], $results); |
| 33 | if ($res && count($results) > 0) { |
| 34 | return true; |
| 35 | } |
| 36 | |
| 37 | $results = []; |
| 38 | $res = $conx->global->query('STAFF', ['email' => $usermail, 'status' => 'AC'], $results); |
| 39 | if ($res && count($results) > 0) { |
| 40 | $res = $conx->global->query('USER', ['objid' => $results[0]['user'], 'status' => ['PA', 'AC']], $results); |
| 41 | if ($res && count($results) > 0) { |
| 42 | $usermail = $results[0]['email']; |
| 43 | return true; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | $logger->error("No valid users/waiters found for email '".$usermail."'."); |
| 48 | return false; |
| 49 | } |
| 50 | |
| 51 | /** |
| 52 | * Sends recovery email and stores authorization key. |
| 53 | * |
| 54 | * Uses central DB for add_authorization; connection resolved inside. |
| 55 | * |
| 56 | * @param \ConxHelper $conx Connection helper. |
| 57 | * @param string $lang Language code. |
| 58 | * @param string $usermail Recipient email. |
| 59 | * @return bool True if email sent and authorization stored. |
| 60 | */ |
| 61 | function inform_to_user(\ConxHelper $conx, string $lang, string $usermail): bool { |
| 62 | $language = new Language($lang); |
| 63 | |
| 64 | $html = ''; |
| 65 | email_begin($html, '@password_recovery_title'); |
| 66 | $content1 = file_get_contents(RECOVER_HTML_DIR.'/1.html'); |
| 67 | $content2 = file_get_contents(RECOVER_HTML_DIR.'/2.html'); |
| 68 | $content3 = file_get_contents(RECOVER_HTML_DIR.'/3.html'); |
| 69 | email_content($html, $content1, $content2, $content3); |
| 70 | email_end($html, '@password_recovery_footer'); |
| 71 | |
| 72 | $replace = []; |
| 73 | $search = [ |
| 74 | '@password_recovery_title', |
| 75 | '@password_recovery_footer', |
| 76 | '@recover_email_reason', |
| 77 | '@recover_email_norespond', |
| 78 | '@recover_email_ignore', |
| 79 | '@recover_email_accessdata', |
| 80 | '@recover_email_follow_link', |
| 81 | '@recover_email_onlogin', |
| 82 | '@recover_email_regenerate' |
| 83 | ]; |
| 84 | foreach ($search as $str) { |
| 85 | $replace[] = $language->translate($str); |
| 86 | } |
| 87 | |
| 88 | srand(); |
| 89 | $recover_authorization_key = sprintf('%04x%04x%04x%04x', rand(0, 0xFFFF), rand(0, 0xFFFF), rand(0, 0xFFFF), rand(0, 0xFFFF)); |
| 90 | $search[] = '@REGENERATE_ONCLICK_URL'; |
| 91 | $replace[] = AppConstants::AppUrl().'login/regenerate?lang='.$lang.'&authorization='.$recover_authorization_key; |
| 92 | |
| 93 | $subject = $language->translate('@password_recovery_title'); |
| 94 | $html = str_replace($search, $replace, $html); |
| 95 | if (email_send($html, AppConstants::NoReplyMail, $usermail, $subject)) { |
| 96 | return add_authorization($conx, $recover_authorization_key, $usermail); |
| 97 | } |
| 98 | |
| 99 | return false; |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Action callable: request password recovery (GET device, username, lang). |
| 104 | * |
| 105 | * Checks user/staff email exists, sends recovery email. |
| 106 | * |
| 107 | * @param string $body Request body (unused). |
| 108 | * @param array<string, mixed> $query Query params: device, username, lang. |
| 109 | * @param \ConxHelper $conx Connection helper (from LoginService; uses ->global for central DB). |
| 110 | * @param \Psr\Log\LoggerInterface $logger Logger (from LoggerFactory). |
| 111 | * @param \UppServices\SessionService $sessionService Session service (unused in recover). |
| 112 | * @return array{output: string, contentType: string} JSON output and content type. |
| 113 | */ |
| 114 | return function (string $body, array $query, \ConxHelper $conx, \Psr\Log\LoggerInterface $logger, \UppServices\SessionService $sessionService): array { |
| 115 | $retval = ApplicationError::Success; |
| 116 | |
| 117 | $deviceid = $query['device'] ?? null; |
| 118 | if (!$deviceid) { |
| 119 | $logger->error("Missing 'device' parameter in url request"); |
| 120 | $retval = ApplicationError::Parameters; |
| 121 | } |
| 122 | |
| 123 | $username = $query['username'] ?? null; |
| 124 | if (success($retval) && !$username) { |
| 125 | $logger->error("Mandatory argument 'username' not provided in url parameters."); |
| 126 | $retval = ApplicationError::Parameters; |
| 127 | } |
| 128 | |
| 129 | $emailForRecovery = null; |
| 130 | if (success($retval) && $username !== null && $username !== '') { |
| 131 | $emailForRecovery = (string) $username; |
| 132 | if (!check_user_mail($conx, $emailForRecovery, $logger)) { |
| 133 | $retval = ApplicationError::NotFound; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | if (success($retval) && $emailForRecovery !== null) { |
| 138 | $lang = (string) ($query['lang'] ?? 'EN'); |
| 139 | if (!inform_to_user($conx, $lang, $emailForRecovery)) { |
| 140 | $logger->warning("Could not set password recovery for '".$emailForRecovery."' email "); |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | if (success($retval) && $emailForRecovery !== null) { |
| 145 | $logger->info("Password recovery request processed for user email address: '".$emailForRecovery."'."); |
| 146 | } |
| 147 | |
| 148 | $result = ['errorcode' => $retval]; |
| 149 | $output = json_encode($result); |
| 150 | return ['output' => $output, 'contentType' => 'application/json; charset=utf-8']; |
| 151 | }; |