Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 7.0.2 -- reduce memory consumption of password expiry processing #394

Merged
merged 7 commits into from
Feb 12, 2025
48 changes: 40 additions & 8 deletions application/common/components/Emailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -776,21 +776,38 @@ public function sendPasswordExpiringEmails()
'status' => 'starting',
];

$users = User::getActiveUnlockedUsers();
$users = \Yii::$app->getDb()->createCommand("SELECT u.*
briskt marked this conversation as resolved.
Show resolved Hide resolved
briskt marked this conversation as resolved.
Show resolved Hide resolved
FROM `user` u
JOIN `password` p ON u.id = p.user_id
LEFT JOIN `email_log` e ON u.id = e.user_id
AND e.message_type = 'password-expiring'
AND e.sent_utc >= CURRENT_DATE() - INTERVAL ? DAY
WHERE u.active = 'yes'
AND u.locked = 'no'
AND p.expires_on < CURRENT_DATE() + INTERVAL 15 DAY
AND p.expires_on >= CURRENT_DATE() # send a different message if expired
AND e.id IS NULL
GROUP BY u.id
HAVING COUNT(*) = 1;")
->bindValue(1, $this->emailRepeatDelayDays)
briskt marked this conversation as resolved.
Show resolved Hide resolved
->queryAll();

$this->logger->info(array_merge($logData, [
'active_users' => count($users)
'users' => count($users)
]));

$numEmailsSent = 0;
foreach ($users as $user) {
foreach ($users as $u) {
$user = new User();
User::populateRecord($user, $u);

/** @var Password $userPassword */
$userPassword = $user->currentPassword;
if ($userPassword) {
// password expiry still needs to be checked because it can be extended by having an active MFA
$passwordExpiry = strtotime($userPassword->getExpiresOn());
if ($passwordExpiry < strtotime(self::PASSWORD_EXPIRING_CUTOFF)
&& !($passwordExpiry < time())
&& !$this->hasUserReceivedMessageRecently($user->id, EmailLog::MESSAGE_TYPE_PASSWORD_EXPIRING)
) {
$this->sendMessageTo(EmailLog::MESSAGE_TYPE_PASSWORD_EXPIRING, $user);
$numEmailsSent++;
Expand Down Expand Up @@ -818,21 +835,36 @@ public function sendPasswordExpiredEmails()
'status' => 'starting',
];

$users = User::getActiveUnlockedUsers();
$users = \Yii::$app->getDb()->createCommand("SELECT u.* FROM `user` u
JOIN `password` p ON u.id = p.user_id
LEFT JOIN `email_log` e ON u.id = e.user_id
AND e.message_type = 'password-expired'
AND e.sent_utc >= CURRENT_DATE() - INTERVAL ? DAY
WHERE u.active = 'yes'
AND u.locked = 'no'
AND p.expires_on <= CURRENT_DATE()
AND e.id IS NULL
GROUP BY u.id
HAVING COUNT(*) = 1;")
->bindValue(1, $this->emailRepeatDelayDays)
->queryAll();

$this->logger->info(array_merge($logData, [
'active_users' => count($users)
'users' => count($users)
]));

$numEmailsSent = 0;
foreach ($users as $user) {
foreach ($users as $u) {
$user = new User();
User::populateRecord($user, $u);

/** @var Password $userPassword */
$userPassword = $user->currentPassword;
if ($userPassword) {
// password expiry still needs to be checked because it can be extended by having an active MFA
$passwordExpiry = strtotime($userPassword->getExpiresOn());
if ($passwordExpiry < time()
&& $passwordExpiry > strtotime(self::PASSWORD_EXPIRED_CUTOFF)
&& !$this->hasUserReceivedMessageRecently($user->id, EmailLog::MESSAGE_TYPE_PASSWORD_EXPIRED)
) {
$this->sendMessageTo(EmailLog::MESSAGE_TYPE_PASSWORD_EXPIRED, $user);
$numEmailsSent++;
Expand Down