You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2022/07/08 19:19:44 UTC
[airavata-django-portal] 03/05: AIRAVATA-3567 email template for user profile complete admin email
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch AIRAVATA-3562
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit 87fe6cd60e5d7df819a9c3051656ad1825dd4a33
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Thu Jun 16 16:58:32 2022 -0400
AIRAVATA-3567 email template for user profile complete admin email
---
.../auth/migrations/0017_auto_20220616_1831.py | 55 ++++++++++++++++++++++
django_airavata/apps/auth/models.py | 11 +++++
django_airavata/apps/auth/serializers.py | 4 +-
django_airavata/apps/auth/utils.py | 36 ++++++++++----
django_airavata/apps/auth/views.py | 3 +-
5 files changed, 99 insertions(+), 10 deletions(-)
diff --git a/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py b/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py
new file mode 100644
index 00000000..47ed7952
--- /dev/null
+++ b/django_airavata/apps/auth/migrations/0017_auto_20220616_1831.py
@@ -0,0 +1,55 @@
+# Generated by Django 3.2.11 on 2022-06-16 18:31
+
+from django.db import migrations
+
+from django_airavata.apps.auth.models import (
+ USER_PROFILE_COMPLETED_TEMPLATE,
+)
+
+
+def default_templates(apps, schema_editor):
+
+ EmailTemplate = apps.get_model("django_airavata_auth", "EmailTemplate")
+ user_profile_completed_template = EmailTemplate(
+ template_type=USER_PROFILE_COMPLETED_TEMPLATE,
+ subject="User {{first_name}} {{last_name}} ({{username}}) has completed their profile",
+ body="""
+ <p>Gateway Portal: {{http_host}}</p>
+ <p>Tenant: {{gateway_id}}</p>
+ <h3>User Profile</h3>
+ <p>Username: {{username}}</p>
+ <p>Name: {{first_name}} {{last_name}}</p>
+ <p>Email: {{email}}</p>
+ {% if extended_profile_values %}
+ <h3>Extended User Profile</h3>
+ <table><tr><th>Name</th><th>Value</th></tr>
+ {% for value in extended_profile_values %}
+ <tr><td>{{ value.ext_user_profile_field.name }}</td>
+ {% if value.value_display_list and value.value_display_list|length > 1 %}
+ <td><ul>
+ {% for display_item in value.value_display_list %}
+ <li>{{ display_item }}</li>
+ {% endfor %}
+ </ul></td>
+ {% elif value.value_display_list and value.value_display_list|length == 1 %}
+ <td>{{ value.value_display_list|first }}</td>
+ {% else %}
+ <td>{{ value.value_display_list }}</td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+ """.strip())
+ user_profile_completed_template.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('django_airavata_auth', '0016_extendeduserprofilefield_required'),
+ ]
+
+ operations = [
+ migrations.RunPython(default_templates)
+ ]
diff --git a/django_airavata/apps/auth/models.py b/django_airavata/apps/auth/models.py
index d4cd2695..6cc658ea 100644
--- a/django_airavata/apps/auth/models.py
+++ b/django_airavata/apps/auth/models.py
@@ -11,6 +11,7 @@ NEW_USER_EMAIL_TEMPLATE = 2
PASSWORD_RESET_EMAIL_TEMPLATE = 3
USER_ADDED_TO_GROUP_TEMPLATE = 4
VERIFY_EMAIL_CHANGE_TEMPLATE = 5
+USER_PROFILE_COMPLETED_TEMPLATE = 6
class EmailVerification(models.Model):
@@ -29,6 +30,7 @@ class EmailTemplate(models.Model):
(PASSWORD_RESET_EMAIL_TEMPLATE, 'Password Reset Email Template'),
(USER_ADDED_TO_GROUP_TEMPLATE, 'User Added to Group Template'),
(VERIFY_EMAIL_CHANGE_TEMPLATE, 'Verify Email Change Template'),
+ (USER_PROFILE_COMPLETED_TEMPLATE, 'User Profile Completed Template'),
)
template_type = models.IntegerField(
primary_key=True, choices=TEMPLATE_TYPE_CHOICES)
@@ -311,6 +313,15 @@ class ExtendedUserProfileValue(models.Model):
return "No"
return None
+ @property
+ def value_display_list(self):
+ """Same as value_display except coerced always to a list."""
+ value_display = self.value_display
+ if value_display is not None and not isinstance(value_display, list):
+ return [value_display]
+ else:
+ return value_display
+
@property
def valid(self):
# if the field is deleted, whatever the value, consider it valid
diff --git a/django_airavata/apps/auth/serializers.py b/django_airavata/apps/auth/serializers.py
index 70db769c..c02162ae 100644
--- a/django_airavata/apps/auth/serializers.py
+++ b/django_airavata/apps/auth/serializers.py
@@ -228,7 +228,9 @@ class ExtendedUserProfileFieldSerializer(serializers.ModelSerializer):
class ExtendedUserProfileValueSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(label='ID', required=False)
text_value = serializers.CharField(required=False, allow_blank=True)
- choices = serializers.ListField(child=serializers.IntegerField(), required=False)
+ # choices must be write_only so that DRF ignores trying to deserialized this related field
+ # deserialization is handled explicitly in to_representation, see below
+ choices = serializers.ListField(child=serializers.IntegerField(), required=False, write_only=True)
other_value = serializers.CharField(required=False, allow_blank=True)
agreement_value = serializers.BooleanField(required=False)
diff --git a/django_airavata/apps/auth/utils.py b/django_airavata/apps/auth/utils.py
index d7ebda8b..cfa53c04 100644
--- a/django_airavata/apps/auth/utils.py
+++ b/django_airavata/apps/auth/utils.py
@@ -129,14 +129,7 @@ def send_new_user_email(request, username, email, first_name, last_name):
})
subject = Template(new_user_email_template.subject).render(context)
body = Template(new_user_email_template.body).render(context)
- msg = EmailMessage(subject=subject,
- body=body,
- from_email=f'"{settings.PORTAL_TITLE}" <{settings.SERVER_EMAIL}>',
- to=[f'"{a[0]}" <{a[1]}>' for a in getattr(settings,
- 'PORTAL_ADMINS',
- settings.ADMINS)])
- msg.content_subtype = 'html'
- msg.send()
+ send_email_to_admins(subject, body)
def send_admin_alert_about_uninitialized_username(request, username, email, first_name, last_name):
@@ -174,6 +167,33 @@ def send_admin_alert_about_uninitialized_username(request, username, email, firs
portal.
</p>
""".strip()).render(context)
+ send_email_to_admins(subject, body)
+
+
+def send_admin_user_completed_profile(request, user_profile):
+ domain, port = split_domain_port(request.get_host())
+ user = user_profile.user
+ extended_profile_values = user_profile.extended_profile_values.filter(
+ ext_user_profile_field__deleted=False).order_by("ext_user_profile_field__order").all()
+ context = Context({
+ "username": user.username,
+ "email": user.email,
+ "first_name": user.first_name,
+ "last_name": user.last_name,
+ "portal_title": settings.PORTAL_TITLE,
+ "gateway_id": settings.GATEWAY_ID,
+ "http_host": domain,
+ "extended_profile_values": extended_profile_values
+ })
+
+ user_profile_completed_template = models.EmailTemplate.objects.get(
+ pk=models.USER_PROFILE_COMPLETED_TEMPLATE)
+ subject = Template(user_profile_completed_template.subject).render(context)
+ body = Template(user_profile_completed_template.body).render(context)
+ send_email_to_admins(subject, body)
+
+
+def send_email_to_admins(subject, body):
msg = EmailMessage(subject=subject,
body=body,
from_email=f'"{settings.PORTAL_TITLE}" <{settings.SERVER_EMAIL}>',
diff --git a/django_airavata/apps/auth/views.py b/django_airavata/apps/auth/views.py
index eb016607..a2c0775f 100644
--- a/django_airavata/apps/auth/views.py
+++ b/django_airavata/apps/auth/views.py
@@ -751,6 +751,7 @@ class ExtendedUserProfileValueViewset(mixins.CreateModelMixin,
return queryset
@action(methods=['POST'], detail=False, url_path="save-all")
+ @atomic
def save_all(self, request, format=None):
user = request.user
user_profile: models.UserProfile = user.user_profile
@@ -761,7 +762,7 @@ class ExtendedUserProfileValueViewset(mixins.CreateModelMixin,
new_valid = user_profile.is_ext_user_profile_valid
if not old_valid and new_valid:
- logger.info("TODO: send email to admin")
+ utils.send_admin_user_completed_profile(request, user_profile)
serializer = self.get_serializer(values, many=True)
return Response(serializer.data)