Skip to content

Commit

Permalink
extract user/email search SQL to a new method on User class
Browse files Browse the repository at this point in the history
  • Loading branch information
briskt committed Feb 11, 2025
1 parent d145728 commit be02f67
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 38 deletions.
42 changes: 4 additions & 38 deletions application/common/components/Emailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -776,35 +776,17 @@ public function sendPasswordExpiringEmails()
'status' => 'starting',
];

$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-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)
->queryAll();
$users = User::getUsersForEmail('password-expiring', $this->emailRepeatDelayDays);

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

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

foreach ($users as $user) {
/** @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())
Expand Down Expand Up @@ -835,33 +817,17 @@ public function sendPasswordExpiredEmails()
'status' => 'starting',
];

$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();
$users = User::getUsersForEmail('password-expired', $this->emailRepeatDelayDays);

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

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

foreach ($users as $user) {
/** @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)
Expand Down
32 changes: 32 additions & 0 deletions application/common/models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -1581,4 +1581,36 @@ public static function exportToSheets()
'status' => 'finish',
]);
}

/*
* Returns a list of active, unlocked users that haven't recently received a given email message.
* @param $template Email template name to use as search criteria
* @param $days Number of days to consider an email sent recently
* @returns User[]
*/
public static function getUsersForEmail(string $template, int $days): array
{
$usersArray = \Yii::$app->getDb()->createCommand("SELECT u.*
FROM `user` u
LEFT JOIN `email_log` e ON u.id = e.user_id
AND e.message_type = :template
AND e.sent_utc >= CURRENT_DATE() - INTERVAL :days DAY
WHERE u.active = 'yes'
AND u.locked = 'no'
AND e.id IS NULL
GROUP BY u.id
HAVING COUNT(*) = 1;")
->bindValue('template', $template)
->bindValue('days', $days)
->queryAll();

$users = [];
foreach ($usersArray as $userData) {
$user = new User();
User::populateRecord($user, $userData);
$users[] = $user;
}

return $users;
}
}

0 comments on commit be02f67

Please sign in to comment.