This is an automated email from the ASF dual-hosted git repository. machristie pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit fef84db1dcc91a9b88d0f2c243ce8099157edf69 Merge: 304016b 125fd07 Author: Marcus Christie <[email protected]> AuthorDate: Wed Jun 9 12:48:23 2021 -0400 Merge branch 'AIRAVATA-3319-handle-missing-name-and-email-attributes-from-cilo' into develop .gitignore | 1 + .../api/static/django_airavata_api/js/index.js | 1 + .../static/django_airavata_api/js/models/User.js | 9 + .../django_airavata_api/js/service_config.js | 24 + django_airavata/apps/auth/.prettierignore | 2 + django_airavata/apps/auth/babel.config.js | 3 + django_airavata/apps/auth/backends.py | 71 +- .../auth/migrations/0007_auto_20200917_1610.py | 43 + .../auth/migrations/0008_auto_20210422_1838.py | 59 + django_airavata/apps/auth/models.py | 41 + django_airavata/apps/auth/package.json | 56 + django_airavata/apps/auth/serializers.py | 78 + .../js/components/UserProfileEditor.vue | 100 + .../js/containers/UserProfileContainer.vue | 89 + .../django_airavata_auth/js/entry-user-profile.js | 8 + .../auth/templates/django_airavata_auth/base.html | 23 + django_airavata/apps/auth/urls.py | 7 +- django_airavata/apps/auth/views.py | 78 +- django_airavata/apps/auth/vue.config.js | 80 + django_airavata/apps/auth/yarn.lock | 8717 ++++++++++++++++++++ django_airavata/settings.py | 12 + .../static/common/js/errors/vuelidateHelpers.js | 4 + django_airavata/static/common/js/index.js | 4 +- django_airavata/templates/base.html | 8 +- docs/dev/new_django_app.md | 6 +- 25 files changed, 9499 insertions(+), 25 deletions(-) diff --cc django_airavata/apps/auth/urls.py index 51bb043,887ed74..5d1e631 --- a/django_airavata/apps/auth/urls.py +++ b/django_airavata/apps/auth/urls.py @@@ -28,5 -32,5 +32,6 @@@ urlpatterns = views.login_desktop_success, name="login_desktop_success"), url(r'^refreshed-token-desktop$', views.refreshed_token_desktop, name="refreshed_token_desktop"), + url(r'^access-token-redirect$', views.access_token_redirect, name="access_token_redirect"), + url(r'^user-profile/', views.user_profile, name="user_profile"), ] diff --cc django_airavata/apps/auth/views.py index 7eefd46,fb30761..914b632 --- a/django_airavata/apps/auth/views.py +++ b/django_airavata/apps/auth/views.py @@@ -5,15 -5,12 +5,16 @@@ from urllib.parse import quote, urlenco from django.conf import settings from django.contrib import messages - from django.contrib.auth import authenticate, login, logout + from django.contrib.auth import authenticate, get_user_model, login, logout from django.contrib.auth.decorators import login_required from django.core.exceptions import ObjectDoesNotExist + from django.db.transaction import atomic from django.forms import ValidationError -from django.http import HttpResponseBadRequest, JsonResponse +from django.http import ( + HttpResponseBadRequest, + HttpResponseForbidden, + JsonResponse +) from django.shortcuts import redirect, render, resolve_url from django.template import Context from django.urls import reverse @@@ -510,13 -512,71 +516,83 @@@ def _create_login_desktop_failed_respon @login_required +def access_token_redirect(request): + redirect_uri = request.GET['redirect_uri'] + config = next(filter(lambda d: d.get('URI') == redirect_uri, + settings.ACCESS_TOKEN_REDIRECT_ALLOWED_URIS), None) + if config is None: + logger.warning(f"redirect_uri value '{redirect_uri}' is not configured " + "in ACCESS_TOKEN_REDIRECT_ALLOWED_URIS setting") + return HttpResponseForbidden("Invalid redirect_uri value") + return redirect(redirect_uri + f"{'&' if '?' in redirect_uri else '?'}{config.get('PARAM_NAME', 'access_token')}=" + f"{quote(request.authz_token.accessToken)}") ++ ++ + def user_profile(request): + return render(request, "django_airavata_auth/base.html", { + 'bundle_name': "user-profile" + }) + + + class IsUserOrReadOnlyForAdmins(permissions.BasePermission): + def has_permission(self, request, view): + return request.user.is_authenticated + + def has_object_permission(self, request, view, obj): + if (request.method in permissions.SAFE_METHODS and + request.is_gateway_admin): + return True + return obj == request.user + + + # TODO: disable deleting and creating? + class UserViewSet(viewsets.ModelViewSet): + serializer_class = serializers.UserSerializer + queryset = get_user_model().objects.all() + permission_classes = [IsUserOrReadOnlyForAdmins] + + def get_queryset(self): + user = self.request.user + if user.is_superuser: + return get_user_model().objects.all() + else: + return get_user_model().objects.get(pk=user.pk) + + @action(detail=False) + def current(self, request): + return redirect(reverse('django_airavata_auth:user-detail', kwargs={'pk': request.user.id})) + + @action(methods=['post'], detail=True) + def resend_email_verification(self, request, pk=None): + pending_email_change = models.PendingEmailChange.objects.get(user=request.user, verified=False) + if pending_email_change is not None: + serializer = serializers.UserSerializer() + 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'] + + try: + pending_email_change = models.PendingEmailChange.objects.get(user=user, verification_code=code) + except models.PendingEmailChange.DoesNotExist: + raise Exception('Verification code is invalid. Please try again.') + pending_email_change.verified = True + pending_email_change.save() + user.email = pending_email_change.email_address + user.save() + user.refresh_from_db() + + try: + user_profile_client = request.profile_service['user_profile'] + airavata_user_profile = user_profile_client.getUserProfileById( + 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) + except Exception as e: + raise Exception(f"Failed to update Airavata User Profile with new email address: {e}") from e + serializer = self.get_serializer(user) + return Response(serializer.data)
