From 948afab1662a81cac1afbc26728529da521ac1fe Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 9 May 2024 11:14:49 -0400 Subject: [PATCH] wip --- src/registrar/config/urls.py | 5 +++ src/registrar/templates/base.html | 5 ++- src/registrar/templates/profile.html | 41 ++++++++++++------- src/registrar/views/__init__.py | 1 + src/registrar/views/user_profile.py | 36 ++++++++++++++++ src/registrar/views/utility/mixins.py | 15 +++++++ .../views/utility/permission_views.py | 23 ++++++++++- 7 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 src/registrar/views/user_profile.py diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 720034150..380cdb803 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -178,6 +178,11 @@ urlpatterns = [ views.DomainAddUserView.as_view(), name="domain-users-add", ), + path( + "user-profile", + views.UserProfileView.as_view(), + name="user-profile", + ), path( "invitation//delete", views.DomainInvitationDeleteView.as_view(http_method_names=["post"]), diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index c0702e78f..efaf46dfa 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -158,8 +158,11 @@
  • | - Sign out + Your profile
  • +
  • + | + Sign out {% else %} Sign in {% endif %} diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index 6a051bfe4..26fa34163 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -3,25 +3,36 @@ {% block title %} Edit your User Profile | {% endblock title %} +{% load static url_helpers %} {% block content %}
    -
    -
    - Your profile -

    - Required fields are marked with an asterisk (*). +

    - - +
    +

    Your profile

    +

    We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

    +

    Contact information

    +

    Review the details below and update any required information. Note that editing this information won’t affect your Login.gov account information.

    + {% include "includes/required_fields.html" %} + +
    +
    + Your profile + {% for field in profile_form %} + + {{ field }} + {% endfor %} +
    + +
    {% endblock content %} diff --git a/src/registrar/views/__init__.py b/src/registrar/views/__init__.py index bd15196d4..4ed5bfa75 100644 --- a/src/registrar/views/__init__.py +++ b/src/registrar/views/__init__.py @@ -14,5 +14,6 @@ from .domain import ( DomainInvitationDeleteView, DomainDeleteUserView, ) +from .user_profile import UserProfileView from .health import * from .index import * diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py new file mode 100644 index 000000000..e24982965 --- /dev/null +++ b/src/registrar/views/user_profile.py @@ -0,0 +1,36 @@ +"""Views for a User Profile. + +""" + +import logging + +from django.contrib import messages +from django.contrib.messages.views import SuccessMessageMixin +from django.db import IntegrityError +from django.http import HttpResponseRedirect +from django.shortcuts import redirect +from django.urls import reverse +from django.views.generic.edit import FormMixin +from django.conf import settings + +from registrar.models import ( + User, +) +from registrar.views.utility.permission_views import UserProfilePermissionView + + +logger = logging.getLogger(__name__) + + +class UserProfileView(UserProfilePermissionView): + """ + Base View for the Domain. Handles getting and setting the domain + in session cache on GETs. Also provides methods for getting + and setting the domain in cache + """ + + template_name = "profile.html" + + # Override get_object to return the logged-in user + def get_object(self, queryset=None): + return self.request.user # Returns the logged-in user \ No newline at end of file diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index c7083ce48..2208b7570 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -382,3 +382,18 @@ class DomainInvitationPermission(PermissionsLoginMixin): return False return True + + +class UserProfilePermission(PermissionsLoginMixin): + """Permission mixin that redirects to user profile if user + has access, otherwise 403""" + + def has_permission(self): + """Check if this user has access. + + If the user is authenticated, they have access + """ + if not self.request.user.is_authenticated: + return False + + return True diff --git a/src/registrar/views/utility/permission_views.py b/src/registrar/views/utility/permission_views.py index f2752c3b5..6f59cc032 100644 --- a/src/registrar/views/utility/permission_views.py +++ b/src/registrar/views/utility/permission_views.py @@ -2,8 +2,9 @@ import abc # abstract base class +from django.contrib.auth import get_user_model from django.views.generic import DetailView, DeleteView, TemplateView -from registrar.models import Domain, DomainRequest, DomainInvitation +from registrar.models import Domain, DomainRequest, DomainInvitation, User from registrar.models.user_domain_role import UserDomainRole from .mixins import ( @@ -13,6 +14,7 @@ from .mixins import ( DomainInvitationPermission, DomainRequestWizardPermission, UserDeleteDomainRolePermission, + UserProfilePermission, ) import logging @@ -142,3 +144,22 @@ class UserDomainRolePermissionDeleteView(UserDeleteDomainRolePermission, DeleteV # variable name in template context for the model object context_object_name = "userdomainrole" + + +class UserProfilePermissionView(UserProfilePermission, DetailView, abc.ABC): + """Abstract base view for user profile view that enforces permissions. + + This abstract view cannot be instantiated. Actual views must specify + `template_name`. + """ + + # DetailView property for what model this is viewing + model = get_user_model() + # variable name in template context for the model object + context_object_name = "user" + + # Abstract property enforces NotImplementedError on an attribute. + @property + @abc.abstractmethod + def template_name(self): + raise NotImplementedError