From 9a606c7dd2a317b0c521f459f930a517b2570bcf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luis=20Z=C3=A1rate=20Montero?=
Date: Sat, 18 May 2024 17:56:27 -0600
Subject: [PATCH] Add check_remove_user_notlogin as WIP
---
.../commands/check_remove_user_notlogin.py | 61 +++++++++++++
.../migrations/0014_create_user_default.py | 11 ++-
.../migrations/0017_merge_20240518_1359.py | 14 +++
.../migrations/0018_deleteuserlist.py | 26 ++++++
src/auth_and_perms/models.py | 9 ++
.../mail/en/user_delete_notification.html | 22 +++++
.../mail/en/user_merge_notification.html | 15 ++++
.../mail/es/user_delete_notification.html | 7 ++
.../mail/es/user_merge_notification.html | 5 ++
.../user_management_notification.html | 18 +---
src/auth_and_perms/users.py | 86 +++++++++++++++++++
src/auth_and_perms/utils.py | 26 ------
src/auth_and_perms/views/users.py | 2 +-
13 files changed, 256 insertions(+), 46 deletions(-)
create mode 100644 src/auth_and_perms/management/commands/check_remove_user_notlogin.py
create mode 100644 src/auth_and_perms/migrations/0017_merge_20240518_1359.py
create mode 100644 src/auth_and_perms/migrations/0018_deleteuserlist.py
create mode 100644 src/auth_and_perms/templates/auth_and_perms/mail/en/user_delete_notification.html
create mode 100644 src/auth_and_perms/templates/auth_and_perms/mail/en/user_merge_notification.html
create mode 100644 src/auth_and_perms/templates/auth_and_perms/mail/es/user_delete_notification.html
create mode 100644 src/auth_and_perms/templates/auth_and_perms/mail/es/user_merge_notification.html
create mode 100644 src/auth_and_perms/users.py
diff --git a/src/auth_and_perms/management/commands/check_remove_user_notlogin.py b/src/auth_and_perms/management/commands/check_remove_user_notlogin.py
new file mode 100644
index 00000000..b0fb68b4
--- /dev/null
+++ b/src/auth_and_perms/management/commands/check_remove_user_notlogin.py
@@ -0,0 +1,61 @@
+from django.conf import settings
+from django.core.management import BaseCommand
+from django.contrib.auth import get_user_model
+from dateutil.relativedelta import relativedelta
+from django.utils.timezone import now
+from django.contrib.sites.models import Site
+from django.test import RequestFactory
+
+from auth_and_perms.models import DeleteUserList
+from auth_and_perms.users import delete_user
+from auth_and_perms.users import send_email_user_management
+
+
+class Command(BaseCommand):
+
+ def enqueue_users(self):
+ User=get_user_model()
+ User.objects.all()
+ year_ago = now() + relativedelta(years=1)
+ deletelist = []
+ for user in User.objects.exclude(username="soporte@organilab.org").filter(
+ deleteuserlist__isnull=True,
+ last_login__lte=year_ago):
+ deletelist.append(DeleteUserList(user=user))
+ if deletelist:
+ DeleteUserList.objects.bulk_create(deletelist)
+
+ print("Actual: ", User.objects.all().count())
+ print("Remove: ", len(deletelist))
+
+ def get_now(self):
+ # fixme: remove this and put now() only
+ return now() #+ relativedelta(months=1, days=1)
+
+ def delete_users(self):
+ User = get_user_model()
+ site = Site.objects.all().last()
+ if site.domain not in settings.ALLOWED_HOSTS:
+ settings.ALLOWED_HOSTS.append(site.domain)
+ request = RequestFactory().get('/')
+
+ request.META['HTTP_HOST']=site.domain
+ request.META['SERVER_PORT']="80" if settings.DEBUG else "443"
+ user_base=User.objects.filter(username="soporte@organilab.org").first()
+ del_count=0
+ for user_delete in DeleteUserList.objects.filter(expiration_date__lte=self.get_now()):
+ send_email_user_management(request, user_base, user_delete, "delete")
+ print(user_delete.user.username)
+ delete_user(user_delete.user, user_base)
+ user_delete.delete()
+ del_count+=1
+ print("Delete users", del_count)
+ print("Actual to users delete ", DeleteUserList.objects.all().count())
+ print("Actual to users ", User.objects.all().count())
+
+ def handle(self, *args, **options) :
+ self.enqueue_users()
+ self.delete_users()
+
+
+
diff --git a/src/auth_and_perms/migrations/0014_create_user_default.py b/src/auth_and_perms/migrations/0014_create_user_default.py
index 12148fa9..693bbe7f 100644
--- a/src/auth_and_perms/migrations/0014_create_user_default.py
+++ b/src/auth_and_perms/migrations/0014_create_user_default.py
@@ -4,9 +4,16 @@
def create_user_default(apps, schema_editor):
User = apps.get_model('auth', 'User')
- User.objects.create(username="soporte@organilab.org", email="soporte@organilab.org",
+ Profile = apps.get_model('auth_and_perms', 'Profile')
+ user=User.objects.create(username="soporte@organilab.org", email="soporte@organilab.org",
first_name="Usuario preservador de integridad")
-
+ Profile.objects.create(
+ user = user,
+ phone_number = "8888888",
+ id_card = "888888",
+ job_position = "Integrity",
+ language = 'es'
+ )
def delete_user_default(apps, schema_editor):
User = apps.get_model('auth', 'User')
User.objects.filter(username="soporte@organilab.org").delete()
diff --git a/src/auth_and_perms/migrations/0017_merge_20240518_1359.py b/src/auth_and_perms/migrations/0017_merge_20240518_1359.py
new file mode 100644
index 00000000..31f23821
--- /dev/null
+++ b/src/auth_and_perms/migrations/0017_merge_20240518_1359.py
@@ -0,0 +1,14 @@
+# Generated by Django 4.1.10 on 2024-05-18 19:59
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('auth_and_perms', '0014_create_user_default'),
+ ('auth_and_perms', '0016_addpermissiontoadmingroup'),
+ ]
+
+ operations = [
+ ]
diff --git a/src/auth_and_perms/migrations/0018_deleteuserlist.py b/src/auth_and_perms/migrations/0018_deleteuserlist.py
new file mode 100644
index 00000000..f16796de
--- /dev/null
+++ b/src/auth_and_perms/migrations/0018_deleteuserlist.py
@@ -0,0 +1,26 @@
+# Generated by Django 4.1.10 on 2024-05-18 19:59
+
+import auth_and_perms.models
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('auth_and_perms', '0017_merge_20240518_1359'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='DeleteUserList',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('creation_date', models.DateTimeField(auto_now=True)),
+ ('expiration_date', models.DateTimeField(default=auth_and_perms.models.user_expiration_date)),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/src/auth_and_perms/models.py b/src/auth_and_perms/models.py
index 06245a65..8c7e8b17 100644
--- a/src/auth_and_perms/models.py
+++ b/src/auth_and_perms/models.py
@@ -1,6 +1,7 @@
import random
import uuid
+from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission, User
@@ -8,6 +9,7 @@
from django.contrib.contenttypes.models import ContentType
from django.core.validators import RegexValidator
from django.db import models
+from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django_otp.plugins.otp_totp.models import TOTPDevice
@@ -133,6 +135,13 @@ class AuthorizedApplication(models.Model):
notification_url = models.URLField()
token = models.TextField()
+def user_expiration_date():
+ return now()+relativedelta(months=1)
+
+class DeleteUserList(models.Model):
+ user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
+ creation_date = models.DateTimeField(auto_now=True)
+ expiration_date = models.DateTimeField(default=user_expiration_date)
class ImpostorLog(models.Model):
impostor = models.ForeignKey(
diff --git a/src/auth_and_perms/templates/auth_and_perms/mail/en/user_delete_notification.html b/src/auth_and_perms/templates/auth_and_perms/mail/en/user_delete_notification.html
new file mode 100644
index 00000000..88ac52e4
--- /dev/null
+++ b/src/auth_and_perms/templates/auth_and_perms/mail/en/user_delete_notification.html
@@ -0,0 +1,22 @@
+{% extends 'gentelella/registration/email_base.html' %}
+{% load i18n %}
+{% block content %}
+{% trans 'Dear' %} {{user_delete.get_full_name}},
+
+ {% trans 'We would like to inform you that the user' %} {{user_delete.username}} {% trans 'was deleted. The reasons for this delete are as follows:' %}
+
+ 1) {% trans 'Account inactive for a long time.' %}
+
+ 2) {% trans 'System purification.' %}
+
+ {% trans 'This measure has been taken to optimize our resources, ensure more efficient management, and enhance the security of our services.' %}
+ {% endif %}
+
+ {% trans 'If you have any questions or require further assistance, please do not hesitate to contact our support team. We will be glad to assist you.' %}
+
+ {% trans 'Sincerely,' %}
+
+ Organilab
+
+
+{% endblock %}
diff --git a/src/auth_and_perms/templates/auth_and_perms/mail/en/user_merge_notification.html b/src/auth_and_perms/templates/auth_and_perms/mail/en/user_merge_notification.html
new file mode 100644
index 00000000..3efcc90b
--- /dev/null
+++ b/src/auth_and_perms/templates/auth_and_perms/mail/en/user_merge_notification.html
@@ -0,0 +1,15 @@
+{% extends 'gentelella/registration/email_base.html' %}
+{% load i18n %}
+{% block content %}
+{% trans 'Dear' %} {{user_base.get_full_name}},
+
+ {% trans 'We would like to inform you that an update has been made to your account information. The reason for this update is as follows:' %}
+
+ {% trans 'Account consolidation by an administrator: An administrator from your organization has decided to consolidate the accounts that belong to you in order to centralize access. This action aims to simplify account management and provide you with a smoother experience when accessing our resources.' %}
+
+ {% trans 'From now on, you can log in to your account using the following username:' %} {{user_base.username}}
+
+ {% trans 'If you do not remember your password, you can use the following link to recover it:' %} {% trans 'Click here' %}
+
+ {% trans 'We appreciate your understanding and cooperation during this account update process. We value your trust in our services and strive to provide you with an optimal experience.' %}
+{% endblock content %}
diff --git a/src/auth_and_perms/templates/auth_and_perms/mail/es/user_delete_notification.html b/src/auth_and_perms/templates/auth_and_perms/mail/es/user_delete_notification.html
new file mode 100644
index 00000000..64379ce2
--- /dev/null
+++ b/src/auth_and_perms/templates/auth_and_perms/mail/es/user_delete_notification.html
@@ -0,0 +1,7 @@
+{% extends 'gentelella/registration/email_base.html' %}
+{% load i18n %}
+{% block content %}
+Esto es un adiĆ³s {{user}}.
+
+No olvides apoyar a Organilab.
+{% endblock %}
diff --git a/src/auth_and_perms/templates/auth_and_perms/mail/es/user_merge_notification.html b/src/auth_and_perms/templates/auth_and_perms/mail/es/user_merge_notification.html
new file mode 100644
index 00000000..c65484e1
--- /dev/null
+++ b/src/auth_and_perms/templates/auth_and_perms/mail/es/user_merge_notification.html
@@ -0,0 +1,5 @@
+{% extends 'gentelella/registration/email_base.html' %}
+{% load i18n %}
+{% block content %}
+Su usuario ha sido mezclado.
+{% endblock %}
diff --git a/src/auth_and_perms/templates/auth_and_perms/user_management_notification.html b/src/auth_and_perms/templates/auth_and_perms/user_management_notification.html
index 8fb2a65f..ac033e32 100644
--- a/src/auth_and_perms/templates/auth_and_perms/user_management_notification.html
+++ b/src/auth_and_perms/templates/auth_and_perms/user_management_notification.html
@@ -15,21 +15,5 @@
{% trans 'We appreciate your understanding and cooperation during this account update process. We value your trust in our services and strive to provide you with an optimal experience.' %}
{% else %}
- {% trans 'Dear' %} {{user_delete.get_full_name}},
-
- {% trans 'We would like to inform you that the user' %} {{user_delete.username}} {% trans 'was deleted. The reasons for this delete are as follows:' %}
-
- 1) {% trans 'Account inactive for a long time.' %}
-
- 2) {% trans 'System purification.' %}
-
- {% trans 'This measure has been taken to optimize our resources, ensure more efficient management, and enhance the security of our services.' %}
- {% endif %}
-
- {% trans 'If you have any questions or require further assistance, please do not hesitate to contact our support team. We will be glad to assist you.' %}
-
- {% trans 'Sincerely,' %}
-
- Organilab
-
+
{% endblock %}
diff --git a/src/auth_and_perms/users.py b/src/auth_and_perms/users.py
new file mode 100644
index 00000000..c1cd2ccf
--- /dev/null
+++ b/src/auth_and_perms/users.py
@@ -0,0 +1,86 @@
+from django.utils.translation import gettext_lazy as _
+from django.conf import settings
+from django.core.mail import send_mail
+from django.template.loader import render_to_string
+from django.db.models.fields.related import ManyToOneRel
+from django.utils.translation import activate, get_language
+
+def send_email_user_management(request, user_base, user_delete, action):
+ schema = request.scheme + "://"
+ if hasattr(user_base, 'profile'):
+ lang = user_base.profile.language
+ oldlang = get_language()
+ context = {
+ 'user_base': user_base,
+ 'user_delete': user_delete,
+ 'domain': schema + request.get_host(),
+ 'action': action
+ }
+ activate(lang)
+ send_mail(subject=_(
+ "Account Update: Merger with Another Account.") if action == "merge" else _(
+ "Account Delete"),
+ message=_("Please use a html reader client"),
+ recipient_list=[user_base.email],
+ from_email=settings.DEFAULT_FROM_EMAIL,
+ html_message=render_to_string(
+ 'auth_and_perms/mail/'+lang+'/user_merge_notification.html',
+ context=context
+ )
+ )
+ activate(oldlang)
+
+
+def send_delete_user_email(user_delete):
+ if hasattr(user_delete, 'profile'):
+ lang = user_delete.profile.language
+ oldlang = get_language()
+ context={'lang': lang,
+ 'user': user_delete}
+ activate(lang)
+ send_mail(subject=_("Thanks for be part of Organilab, we will miss you."),
+ message=_("Your account was removed"),
+ recipient_list=[user_delete.email],
+ from_email=settings.DEFAULT_FROM_EMAIL,
+ html_message=render_to_string(
+ "auth_and_perms/mail/"+lang+"/user_delete_notification.html",
+ context=context
+ )
+ )
+ activate(oldlang)
+
+def merge_information_user(to_delete, to_related):
+ for field in to_delete._meta.get_fields():
+ if field.name == 'sga_substance':
+ print(field)
+ if field.name in ['user_permissions', 'groups', 'profile', 'usertotpdevice',
+ 'registrationuser', 'authorizedapplication', 'deleteuserlist',
+ 'auth_token', 'chunked_uploads', 'totpdevice']:
+ continue
+ if isinstance(field, ManyToOneRel):
+ #print(field.name,field.target_field.model, field.field.name)
+ field.target_field.model.objects.filter(**{field.field.name: to_delete}).update(
+ **{field.field.name: to_related}
+ )
+ if hasattr(to_delete, 'profile') and hasattr(to_related, 'profile'):
+ del_profile=to_delete.profile
+ merge_profile = to_related.profile
+ for field in del_profile._meta.get_fields():
+ if field.name in ['profilepermission']:
+ continue
+ if isinstance(field, ManyToOneRel):
+ field.target_field.model.objects.filter(
+ **{field.field.name: del_profile}).update(
+ **{field.field.name: merge_profile}
+ )
+
+
+def delete_user(to_delete, to_related):
+ merge_information_user(to_delete, to_related)
+ send_delete_user_email(to_delete)
+ print("Deleting:", to_delete.username)
+ print(to_delete.delete())
+
+def user_management(request, user_base, user_delete, action):
+ send_email_user_management(request, user_base, user_delete, action)
+ delete_user(user_delete, user_base)
diff --git a/src/auth_and_perms/utils.py b/src/auth_and_perms/utils.py
index 46b8b6f1..2a98d99f 100644
--- a/src/auth_and_perms/utils.py
+++ b/src/auth_and_perms/utils.py
@@ -65,32 +65,6 @@ def send_email(request, user):
)
-def send_email_user_management(request, user_base, user_delete, action):
- schema = request.scheme + "://"
-
- context = {
- 'user_base': user_base,
- 'user_delete': user_delete,
- 'domain': schema + request.get_host(),
- 'action': action
- }
- send_mail(subject=_(
- "Account Update: Merger with Another Account.") if action == "merge" else _(
- "Account Delete"),
- message="Por favor use un visor de html",
- recipient_list=[user_base.email],
- from_email=settings.DEFAULT_FROM_EMAIL,
- html_message=render_to_string(
- 'auth_and_perms/user_management_notification.html',
- context=context
- )
- )
-
-
-def user_management(request, user_base, user_delete, action):
- send_email_user_management(request, user_base, user_delete, action)
- user_delete.delete()
-
def get_ip_address(request):
"""
diff --git a/src/auth_and_perms/views/users.py b/src/auth_and_perms/views/users.py
index b97bb55c..e140fd66 100644
--- a/src/auth_and_perms/views/users.py
+++ b/src/auth_and_perms/views/users.py
@@ -5,7 +5,7 @@
from django.utils.translation import gettext_lazy as _
from auth_and_perms.forms import MergeUsers, UserForm
-from auth_and_perms.utils import user_management
+from auth_and_perms.users import user_management
def users_list(request):