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 2021/05/27 21:26:34 UTC

[airavata-django-portal] branch AIRAVATA-3319-handle-missing-name-and-email-attributes-from-cilo updated: AIRAVATA-3455 Add success notification when email changes

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch AIRAVATA-3319-handle-missing-name-and-email-attributes-from-cilo
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git


The following commit(s) were added to refs/heads/AIRAVATA-3319-handle-missing-name-and-email-attributes-from-cilo by this push:
     new 0c44921  AIRAVATA-3455 Add success notification when email changes
0c44921 is described below

commit 0c44921fb2e6dbbb7033895d043f67cf202bec01
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Thu May 27 16:48:24 2021 -0400

    AIRAVATA-3455 Add success notification when email changes
---
 .../static/django_airavata_api/js/models/User.js   |  2 +-
 .../django_airavata_api/js/service_config.js       |  8 ++++
 django_airavata/apps/auth/serializers.py           |  8 ++--
 .../js/components/UserProfileEditor.vue            |  5 +++
 .../js/containers/UserProfileContainer.vue         | 31 ++++++++++++++--
 django_airavata/apps/auth/urls.py                  |  2 -
 django_airavata/apps/auth/views.py                 | 43 +++++++---------------
 7 files changed, 59 insertions(+), 40 deletions(-)

diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/User.js b/django_airavata/apps/api/static/django_airavata_api/js/models/User.js
index 1790a57..53cbf79 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/User.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/User.js
@@ -1,6 +1,6 @@
 import BaseModel from "./BaseModel";
 
-const FIELDS = ["id", "username", "first_name", "last_name", "email"];
+const FIELDS = ["id", "username", "first_name", "last_name", "email", "pending_email_change"];
 
 export default class User extends BaseModel {
   constructor(data = {}) {
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
index fb2392b..4d5d39b 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
@@ -382,6 +382,14 @@ export default {
         url: "/auth/users/<lookup>/resend_email_verification/",
         requestType: "post",
       },
+      verifyEmailChange: {
+        url: "/auth/users/<lookup>/verify_email_change/",
+        requestType: "post",
+        bodyParams: {
+          name: "data",
+        },
+        modelClass: User,
+      },
     },
     modelClass: User,
   },
diff --git a/django_airavata/apps/auth/serializers.py b/django_airavata/apps/auth/serializers.py
index d5134bb..f12854e 100644
--- a/django_airavata/apps/auth/serializers.py
+++ b/django_airavata/apps/auth/serializers.py
@@ -1,4 +1,5 @@
 import logging
+from urllib.parse import urlencode
 
 from django.conf import settings
 from django.contrib.auth import get_user_model
@@ -60,10 +61,9 @@ class UserSerializer(serializers.ModelSerializer):
 
     def _send_email_verification_link(self, request, pending_email_change):
 
-        verification_uri = request.build_absolute_uri(
-            reverse(
-                'django_airavata_auth:verify_email_change', kwargs={
-                    'code': pending_email_change.verification_code}))
+        verification_uri = (
+            request.build_absolute_uri(reverse('django_airavata_auth:user_profile')) +
+            '?' + urlencode({"code": pending_email_change.verification_code}))
         logger.debug(
             "verification_uri={}".format(verification_uri))
 
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/UserProfileEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/UserProfileEditor.vue
index c80a6d1..9ccd0fe 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/components/UserProfileEditor.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/components/UserProfileEditor.vue
@@ -46,6 +46,11 @@ export default {
       return JSON.parse(JSON.stringify(this.value));
     },
   },
+  watch: {
+    value() {
+      this.user = this.cloneValue();
+    }
+  }
 };
 </script>
 
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
index e34e269..389b965 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/containers/UserProfileContainer.vue
@@ -19,9 +19,16 @@ export default {
   components: { UserProfileEditor },
   name: "user-profile-container",
   created() {
-    services.UserService.current().then((user) => {
-      this.user = user;
-    });
+    services.UserService.current()
+      .then((user) => {
+        this.user = user;
+      })
+      .then(() => {
+        const queryParams = new URLSearchParams(window.location.search);
+        if (queryParams.has("code")) {
+          this.verifyEmailChange(queryParams.get("code"));
+        }
+      });
   },
   data() {
     return {
@@ -50,6 +57,24 @@ export default {
         );
       });
     },
+    verifyEmailChange(code) {
+      services.UserService.verifyEmailChange({
+        lookup: this.user.id,
+        data: { code: code },
+      }).then((user) => {
+        // User now updated with email change
+        this.user = user;
+        notifications.NotificationList.add(
+          new notifications.Notification({
+            type: "SUCCESS",
+            message: "Email address verified and updated",
+            duration: 5,
+          })
+        );
+        // Update URL, removing the code from the query string
+        window.history.replaceState({}, '', '/auth/user-profile/');
+      });
+    },
   },
 };
 </script>
diff --git a/django_airavata/apps/auth/urls.py b/django_airavata/apps/auth/urls.py
index d8de4a2..887ed74 100644
--- a/django_airavata/apps/auth/urls.py
+++ b/django_airavata/apps/auth/urls.py
@@ -33,6 +33,4 @@ urlpatterns = [
     url(r'^refreshed-token-desktop$', views.refreshed_token_desktop,
         name="refreshed_token_desktop"),
     url(r'^user-profile/', views.user_profile, name="user_profile"),
-    url(r'^verify-email-change/(?P<code>[\w-]+)/$', views.verify_email_change,
-        name="verify_email_change"),
 ]
diff --git a/django_airavata/apps/auth/views.py b/django_airavata/apps/auth/views.py
index 5261b07..dfa9c22 100644
--- a/django_airavata/apps/auth/views.py
+++ b/django_airavata/apps/auth/views.py
@@ -18,6 +18,7 @@ from django.views.decorators.debug import sensitive_variables
 from requests_oauthlib import OAuth2Session
 from rest_framework import permissions, viewsets
 from rest_framework.decorators import action
+from rest_framework.response import Response
 
 from django_airavata.apps.auth import serializers
 
@@ -553,41 +554,23 @@ class UserViewSet(viewsets.ModelViewSet):
             serializer._send_email_verification_link(request, pending_email_change)
         return JsonResponse({})
 
+    @action(methods=['post'], detail=True)
+    @atomic
+    def verify_email_change(self, request, pk=None):
+        user = self.get_object()
+        code = request.data['code']
 
-@login_required
-@atomic
-def verify_email_change(request, code):
-    try:
-        pending_email_change = models.PendingEmailChange.objects.get(user=request.user, verification_code=code)
+        pending_email_change = models.PendingEmailChange.objects.get(user=user, verification_code=code)
         pending_email_change.verified = True
         pending_email_change.save()
-        request.user.email = pending_email_change.email_address
-        request.user.save()
+        user.email = pending_email_change.email_address
+        user.save()
+        user.refresh_from_db()
 
         user_profile_client = request.profile_service['user_profile']
         airavata_user_profile = user_profile_client.getUserProfileById(
-            request.authz_token, request.user.username, settings.GATEWAY_ID)
+            request.authz_token, user.username, settings.GATEWAY_ID)
         airavata_user_profile.emails = [pending_email_change.email_address]
         user_profile_client.updateUserProfile(request.authz_token, airavata_user_profile)
-
-        # TODO: add success message
-        return redirect(reverse('django_airavata_auth:user_profile'))
-    except ObjectDoesNotExist:
-        # if doesn't exist, give user a form where they can enter their
-        # username to resend verification code
-        logger.exception("PendingEmailChange object doesn't exist for "
-                         "code {}".format(code))
-        # TODO: add error message
-        # messages.error(
-        #     request,
-        #     "Email verification failed. Please enter your username and we "
-        #     "will send you another email verification link.")
-        return redirect(reverse('django_airavata_auth:user_profile'))
-    except Exception:
-        logger.exception("Email change verification processing failed!")
-        # TODO: add error message
-        # messages.error(
-        #     request,
-        #     "Email verification failed. Please try clicking the email "
-        #     "verification link again later.")
-        return redirect(reverse('django_airavata_auth:user_profile'))
+        serializer = self.get_serializer(user)
+        return Response(serializer.data)