token ?? ''); $password = (string)($body->password ?? ''); if (strlen($password) < 8) { error_out(422, 'validation'); } $stmt = $pdo->prepare( 'SELECT id, email, expires_at FROM password_resets WHERE token_hash = ?' ); $stmt->execute([hash('sha256', $token)]); $reset = $stmt->fetch(); if ( !is_array($reset) || (int)$reset['expires_at'] < time() ) { error_out(400, 'token_invalid'); } $stmt = $pdo->prepare('UPDATE users SET pass_hash = ? WHERE email = ?'); $stmt->execute([ password_hash($password, PASSWORD_DEFAULT), (string)$reset['email'], ]); // Токен одноразовый: удаляем использованный; заодно чистим просроченные. $stmt = $pdo->prepare('DELETE FROM password_resets WHERE id = ?'); $stmt->execute([(int)$reset['id']]); $stmt = $pdo->prepare('DELETE FROM password_resets WHERE expires_at < ?'); $stmt->execute([time()]); json_out(['ok' => true]); } catch (Throwable $e) { error_log('password-reset/confirm: ' . $e->getMessage()); error_out(500, 'internal'); }