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

Remove inactive users #305

Merged
merged 17 commits into from Aug 3, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
146 changes: 146 additions & 0 deletions resources/RemoveInactiveUsersRunner.php
@@ -0,0 +1,146 @@
<?php
require_once dirname(__FILE__) . "/../lib/Doctrine/bootstrap.php";
require dirname(__FILE__) . '/../lib/Doctrine/bootstrap_doctrine.php';
require_once dirname(__FILE__) . '/../lib/Gocdb_Services/User.php';
require_once dirname(__FILE__) . '/../lib/Gocdb_Services/Factory.php';

// Configure script options
$longOptions = array(
// Required Option. After this many months, users will receive email warnings.
"warning_threshold:",
// Required Option. After this many months, users will be deleted.
"deletion_threshold:",
);

$options = getopt("", $longOptions);

// Handle the cases where options were not passed.

if (isset($options["warning_threshold"])) {
$warningThreshold = $options["warning_threshold"];
} else {
echo "Error: warning_threshold option must be set.\n";
usage();
return;
};

if (isset($options["deletion_threshold"])) {
$deletionThreshold = $options["deletion_threshold"];
} else {
echo "Error: deletion_threshold option must be set.\n";
usage();
return;
};

$dql = "SELECT u FROM User u";
$users = $entityManager->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 <gocdb-admins@mailman.egi.eu>";
$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);
}