diff --git a/resources/RemoveInactiveUsersRunner.php b/resources/RemoveInactiveUsersRunner.php new file mode 100644 index 000000000..dd7065589 --- /dev/null +++ b/resources/RemoveInactiveUsersRunner.php @@ -0,0 +1,146 @@ +createQuery($dql)->getResult(); + +echo "Scanning user login dates in database at: ".date('D, d M Y H:i:s')."\n"; + +$today = new DateTime(); + +foreach ($users as $user) { + echo 'User ID: ' . $user->getId() . "\n"; + + $creationDate = $user->getCreationDate(); + $creationStr = $creationDate->format('Y-m-d H:i:s'); + + $lastLoginDate = $user->getLastLoginDate(); + + if (!$user->getAPIAuthenticationEntities()->isEmpty()) { + // Prevent creating orphaned API credentials. + echo "Cannot delete a user with attached API credentials.\n"; + // Move onto the next users. + continue; + } + + if ($lastLoginDate) { // null lastLoginDate check + $interval = $today->diff($lastLoginDate); + } else { // This might only be run once, since new users always have field filled. + echo "User has no lastLoginDate (it may have been a very long time.)\n"; + echo "Deleting user.\n"; + deleteUser($user, $entityManager); + echo "\n"; + // Move onto the next users. + continue; + } + + $elapsedMonths = (int) $interval->format('%a') / 30; + echo 'Months elapsed since last login: ' . $elapsedMonths . "\n"; + + if ($elapsedMonths > $deletionThreshold) { // Delete user + echo "Deleting user\n"; + deleteUser($user, $entityManager); + } elseif ($elapsedMonths > $warningThreshold) { // Warn user + echo "Sending user warning email.\n"; + sendWarningEmail($user, $elapsedMonths, $deletionThreshold); + } elseif ($elapsedMonths < $warningThreshold) { // Do Nothing + echo "Doing nothing.\n"; + } +} + +$entityManager->flush(); +echo "Completed ok: ".date('D, d M Y H:i:s'); + +function usage() { + echo "Usage: " . + "RemoveInactiveUsersRunner.php " . + "--warning_threshold X " . + "--deletion_threshold Y" . + "\n\n"; + echo "Options:\n\n"; + echo "--warning_threshold X " . + " After this many months, users will receive email warnings." . + "\n"; + echo "--deletion_threshold Y" . + " After this many months, users will be deleted." . + "\n"; + + echo "\n"; +}; + +function deleteUser($user, $entityManager) +{ + $entityManager->getConnection()->beginTransaction(); + try { + $entityManager->remove($user); + $entityManager->flush(); + $entityManager->getConnection()->commit(); + echo "User deleted.\n"; + } catch (\Exception $e) { + $entityManager->getConnection()->rollback(); + $entityManager->close(); + echo "User not deleted.\n"; + throw $e; + } +} + +function sendWarningEmail($user, $elapsedMonths, $deletionThreshold) +{ + $emailAddress = $user->getEmail(); + + // Email content + $headers = "From: GOCDB "; + $subject = "GOCDB: User account deletion notice"; + + $body = "Dear ". $user->getForename() .",\n\n" . + "Your GOCDB account, associated with the following " . + "identifiers, has not been signed into during the last " . + floor($elapsedMonths) . " months and will be deleted when " . + "this period of inactivity reaches " . + $deletionThreshold . " months.\n\n"; + + $body .= "Identifiers:\n"; + foreach ($user->getUserIdentifiers() as $identifier) { + $body .= " - " . $identifier->getKeyName() .": " . $identifier->getKeyValue(). "\n"; + } + + $body .= "\n"; + $body .= "You can prevent the deletion of this account by visiting the " . + "GOCDB portal while authenticated with one of the above " . + "identifiers.\n"; + + + // Handle all mail related printing/debugging + \Factory::getEmailService()->send($emailAddress, $subject, $body, $headers); +}