-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1025 from kartoza/merge-duplicate-emails
patch: merge duplicate emails
- Loading branch information
Showing
3 changed files
with
108 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from django.core.management.base import BaseCommand | ||
from django.db import transaction | ||
from django.contrib.auth.models import User | ||
from django.core.mail import send_mail | ||
from django.template.loader import render_to_string | ||
from django.conf import settings | ||
from minisass_authentication.models import ( | ||
UserProfile, | ||
PasswordHistory | ||
) | ||
from monitor.models import ( | ||
Observations, | ||
Sites | ||
) | ||
from django.contrib.sites.models import Site | ||
|
||
class Command(BaseCommand): | ||
help = 'Merge users with duplicate emails, reassign related objects, and delete specific users/bots' | ||
|
||
def handle(self, *args, **kwargs): | ||
self.delete_specific_users() | ||
self.merge_duplicate_users() | ||
|
||
@transaction.atomic | ||
def delete_specific_users(self): | ||
users_to_delete = User.objects.filter( | ||
first_name='James', | ||
last_name='Smith', | ||
date_joined__date=models.F('last_login__date'), | ||
date_joined__lt='2023-01-01' | ||
) | ||
|
||
for user in users_to_delete: | ||
UserProfile.objects.filter(user=user).delete() | ||
PasswordHistory.objects.filter(user=user).delete() | ||
Sites.objects.filter(user=user).delete() | ||
Observations.objects.filter(user=user).delete() | ||
user.delete() | ||
|
||
self.stdout.write(self.style.SUCCESS('Successfully deleted specific users based on criteria.')) | ||
|
||
|
||
@transaction.atomic | ||
def merge_duplicate_users(self): | ||
duplicate_emails = User.objects.values('email').annotate(count=models.Count('id')).filter(count__gt=1) | ||
for item in duplicate_emails: | ||
email = item['email'] | ||
users = User.objects.filter(email=email) | ||
primary_user = users.first() # Keep the first user as the primary | ||
|
||
for user in users.exclude(id=primary_user.id): | ||
# Reassign related objects to primary user | ||
UserProfile.objects.filter(user=user).update(user=primary_user) | ||
PasswordHistory.objects.filter(user=user).update(user=primary_user) | ||
Sites.objects.filter(user=user).update(user=primary_user) | ||
Observations.objects.filter(user=user).update(user=primary_user) | ||
|
||
# Delete the duplicate user | ||
user.delete() | ||
|
||
# Ensure email is unique | ||
primary_user.email = email | ||
primary_user.save() | ||
|
||
# Send notification email | ||
self.send_notification_email(primary_user) | ||
|
||
self.stdout.write(self.style.SUCCESS('Successfully merged users with duplicate emails.')) | ||
|
||
def send_notification_email(self, user): | ||
subject = 'Important: Your miniSASS Accounts Have Been Merged' | ||
login_url = Site.objects.get_current().domain | ||
message = render_to_string('duplicate_email_merge_notification.html', { | ||
'user': user, | ||
'login_url': login_url, | ||
}) | ||
send_mail( | ||
subject, | ||
message, | ||
settings.CONTACT_US_RECEPIENT_EMAIL, | ||
[user.email], | ||
fail_silently=False, | ||
html_message=message, | ||
) |
24 changes: 24 additions & 0 deletions
24
django_project/minisass/templates/duplicate_email_merge_notification.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Account Merge Notification</title> | ||
</head> | ||
<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; color: #333; margin: 0; padding: 0;"> | ||
<div style="max-width: 600px; margin: 20px auto; padding: 20px; background-color: #fff; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"> | ||
<div style="background-color: #0e4981; color: #fff; text-align: center; padding: 20px; border-radius: 8px;"> | ||
<span style="font-size: 24px; font-weight: bold;">miniSASS</span> | ||
</div> | ||
|
||
<h2>Account Merge Notification</h2> | ||
<p>Dear {{ user.username }},</p> | ||
<p>We have identified multiple accounts registered with your email address and have merged them into a single account to ensure data consistency and better user experience.</p> | ||
<p>Please log in to your account and update your password at your earliest convenience to ensure your account's security:</p> | ||
<p><a href="{{ login_url }}" style="display: inline-block; padding: 10px 20px; background-color: #288b31; color: #fff; text-decoration: none; border-radius: 5px;">Login to miniSASS</a></p> | ||
<p>If the button above doesn't work, you can also <a href="{{ login_url }}" style="color: #007bff; text-decoration: none;">click here</a> or copy and paste the following link into your browser:</p> | ||
<p>{{ login_url }}</p> | ||
<p>If you have any questions, feel free to contact us.</p> | ||
<p>Thank you,<br> The miniSASS Team</p> | ||
</div> | ||
</body> | ||
</html> |