mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-22 02:36:02 +02:00
Merge pull request #2857 from cisagov/es/2729-domain-manager-updates
#2729: Update Add a Domain Manager page - [ES]
This commit is contained in:
commit
ce7064da2b
5 changed files with 104 additions and 35 deletions
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
import random
|
||||||
from faker import Faker
|
from faker import Faker
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
|
@ -51,23 +52,24 @@ class UserPortfolioPermissionFixture:
|
||||||
|
|
||||||
user_portfolio_permissions_to_create = []
|
user_portfolio_permissions_to_create = []
|
||||||
for user in users:
|
for user in users:
|
||||||
for portfolio in portfolios:
|
# Assign a random portfolio to a user
|
||||||
try:
|
portfolio = random.choice(portfolios) # nosec
|
||||||
if not UserPortfolioPermission.objects.filter(user=user, portfolio=portfolio).exists():
|
try:
|
||||||
user_portfolio_permission = UserPortfolioPermission(
|
if not UserPortfolioPermission.objects.filter(user=user, portfolio=portfolio).exists():
|
||||||
user=user,
|
user_portfolio_permission = UserPortfolioPermission(
|
||||||
portfolio=portfolio,
|
user=user,
|
||||||
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
|
portfolio=portfolio,
|
||||||
additional_permissions=[UserPortfolioPermissionChoices.EDIT_MEMBERS],
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
|
||||||
)
|
additional_permissions=[UserPortfolioPermissionChoices.EDIT_MEMBERS],
|
||||||
user_portfolio_permissions_to_create.append(user_portfolio_permission)
|
)
|
||||||
else:
|
user_portfolio_permissions_to_create.append(user_portfolio_permission)
|
||||||
logger.info(
|
else:
|
||||||
f"Permission exists for user '{user.username}' "
|
logger.info(
|
||||||
f"on portfolio '{portfolio.organization_name}'."
|
f"Permission exists for user '{user.username}' "
|
||||||
)
|
f"on portfolio '{portfolio.organization_name}'."
|
||||||
except Exception as e:
|
)
|
||||||
logger.warning(e)
|
except Exception as e:
|
||||||
|
logger.warning(e)
|
||||||
|
|
||||||
# Bulk create permissions
|
# Bulk create permissions
|
||||||
cls._bulk_create_permissions(user_portfolio_permissions_to_create)
|
cls._bulk_create_permissions(user_portfolio_permissions_to_create)
|
||||||
|
|
|
@ -4,11 +4,31 @@
|
||||||
{% block title %}Add a domain manager | {% endblock %}
|
{% block title %}Add a domain manager | {% endblock %}
|
||||||
|
|
||||||
{% block domain_content %}
|
{% block domain_content %}
|
||||||
|
{% block breadcrumb %}
|
||||||
|
{% url 'domain-users' pk=domain.id as url %}
|
||||||
|
<nav class="usa-breadcrumb padding-top-0" aria-label="Domain manager breadcrumb">
|
||||||
|
<ol class="usa-breadcrumb__list">
|
||||||
|
<li class="usa-breadcrumb__list-item">
|
||||||
|
<a href="{{ url }}" class="usa-breadcrumb__link"><span>Domain managers</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||||
|
<span>Add a domain manager</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
{% endblock breadcrumb %}
|
||||||
<h1>Add a domain manager</h1>
|
<h1>Add a domain manager</h1>
|
||||||
|
{% if has_organization_feature_flag %}
|
||||||
<p>You can add another user to help manage your domain. They will need to sign
|
<p>
|
||||||
in to the .gov registrar with their Login.gov account.
|
You can add another user to help manage your domain. Users can only be a member of one .gov organization,
|
||||||
|
and they'll need to sign in with their Login.gov account.
|
||||||
</p>
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<p>
|
||||||
|
You can add another user to help manage your domain. They will need to sign in to the .gov registrar with
|
||||||
|
their Login.gov account.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<form class="usa-form usa-form--large" method="post" novalidate>
|
<form class="usa-form usa-form--large" method="post" novalidate>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Domain managers can update all information related to a domain within the
|
Domain managers can update all information related to a domain within the
|
||||||
.gov registrar, including contact details, senior official, security
|
.gov registrar, including including security email and DNS name servers.
|
||||||
email, and DNS name servers.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul class="usa-list">
|
<ul class="usa-list">
|
||||||
|
@ -17,7 +16,8 @@
|
||||||
<li>After adding a domain manager, an email invitation will be sent to that user with
|
<li>After adding a domain manager, an email invitation will be sent to that user with
|
||||||
instructions on how to set up an account.</li>
|
instructions on how to set up an account.</li>
|
||||||
<li>All domain managers must keep their contact information updated and be responsive if contacted by the .gov team.</li>
|
<li>All domain managers must keep their contact information updated and be responsive if contacted by the .gov team.</li>
|
||||||
<li>Domains must have at least one domain manager. You can’t remove yourself as a domain manager if you’re the only one assigned to this domain. Add another domain manager before you remove yourself from this domain.</li>
|
<li>All domain managers will be notified when updates are made to this domain.</li>
|
||||||
|
<li>Domains must have at least one domain manager. You can’t remove yourself as a domain manager if you’re the only one assigned to this domain.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% if domain.permissions %}
|
{% if domain.permissions %}
|
||||||
|
|
|
@ -23,6 +23,15 @@ class InvalidDomainError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OutsideOrgMemberError(ValueError):
|
||||||
|
"""
|
||||||
|
Error raised when an org member tries adding a user from a different .gov org.
|
||||||
|
To be deleted when users can be members of multiple orgs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ActionNotAllowed(Exception):
|
class ActionNotAllowed(Exception):
|
||||||
"""User accessed an action that is not
|
"""User accessed an action that is not
|
||||||
allowed by the current state"""
|
allowed by the current state"""
|
||||||
|
|
|
@ -21,8 +21,10 @@ from registrar.models import (
|
||||||
DomainRequest,
|
DomainRequest,
|
||||||
DomainInformation,
|
DomainInformation,
|
||||||
DomainInvitation,
|
DomainInvitation,
|
||||||
|
PortfolioInvitation,
|
||||||
User,
|
User,
|
||||||
UserDomainRole,
|
UserDomainRole,
|
||||||
|
UserPortfolioPermission,
|
||||||
PublicContact,
|
PublicContact,
|
||||||
)
|
)
|
||||||
from registrar.utility.enums import DefaultEmail
|
from registrar.utility.enums import DefaultEmail
|
||||||
|
@ -35,9 +37,11 @@ from registrar.utility.errors import (
|
||||||
DsDataErrorCodes,
|
DsDataErrorCodes,
|
||||||
SecurityEmailError,
|
SecurityEmailError,
|
||||||
SecurityEmailErrorCodes,
|
SecurityEmailErrorCodes,
|
||||||
|
OutsideOrgMemberError,
|
||||||
)
|
)
|
||||||
from registrar.models.utility.contact_error import ContactError
|
from registrar.models.utility.contact_error import ContactError
|
||||||
from registrar.views.utility.permission_views import UserDomainRolePermissionDeleteView
|
from registrar.views.utility.permission_views import UserDomainRolePermissionDeleteView
|
||||||
|
from registrar.utility.waffle import flag_is_active_for_user
|
||||||
|
|
||||||
from ..forms import (
|
from ..forms import (
|
||||||
SeniorOfficialContactForm,
|
SeniorOfficialContactForm,
|
||||||
|
@ -778,7 +782,18 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
"""Get an absolute URL for this domain."""
|
"""Get an absolute URL for this domain."""
|
||||||
return self.request.build_absolute_uri(reverse("domain", kwargs={"pk": self.object.id}))
|
return self.request.build_absolute_uri(reverse("domain", kwargs={"pk": self.object.id}))
|
||||||
|
|
||||||
def _send_domain_invitation_email(self, email: str, requestor: User, add_success=True):
|
def _is_member_of_different_org(self, email, requestor, requested_user):
|
||||||
|
"""Verifies if an email belongs to a different organization as a member or invited member."""
|
||||||
|
# Check if user is a already member of a different organization than the requestor's org
|
||||||
|
requestor_org = UserPortfolioPermission.objects.filter(user=requestor).first().portfolio
|
||||||
|
existing_org_permission = UserPortfolioPermission.objects.filter(user=requested_user).first()
|
||||||
|
existing_org_invitation = PortfolioInvitation.objects.filter(email=email).first()
|
||||||
|
|
||||||
|
return (existing_org_permission and existing_org_permission.portfolio != requestor_org) or (
|
||||||
|
existing_org_invitation and existing_org_invitation.portfolio != requestor_org
|
||||||
|
)
|
||||||
|
|
||||||
|
def _send_domain_invitation_email(self, email: str, requestor: User, requested_user=None, add_success=True):
|
||||||
"""Performs the sending of the domain invitation email,
|
"""Performs the sending of the domain invitation email,
|
||||||
does not make a domain information object
|
does not make a domain information object
|
||||||
email: string- email to send to
|
email: string- email to send to
|
||||||
|
@ -803,6 +818,13 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Check is user is a member or invited member of a different org from this domain's org
|
||||||
|
if flag_is_active_for_user(requestor, "organization_feature") and self._is_member_of_different_org(
|
||||||
|
email, requestor, requested_user
|
||||||
|
):
|
||||||
|
add_success = False
|
||||||
|
raise OutsideOrgMemberError
|
||||||
|
|
||||||
# Check to see if an invite has already been sent
|
# Check to see if an invite has already been sent
|
||||||
try:
|
try:
|
||||||
invite = DomainInvitation.objects.get(email=email, domain=self.object)
|
invite = DomainInvitation.objects.get(email=email, domain=self.object)
|
||||||
|
@ -859,16 +881,21 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
Throws EmailSendingError."""
|
Throws EmailSendingError."""
|
||||||
requested_email = form.cleaned_data["email"]
|
requested_email = form.cleaned_data["email"]
|
||||||
requestor = self.request.user
|
requestor = self.request.user
|
||||||
|
email_success = False
|
||||||
# look up a user with that email
|
# look up a user with that email
|
||||||
try:
|
try:
|
||||||
requested_user = User.objects.get(email=requested_email)
|
requested_user = User.objects.get(email=requested_email)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
# no matching user, go make an invitation
|
# no matching user, go make an invitation
|
||||||
|
email_success = True
|
||||||
return self._make_invitation(requested_email, requestor)
|
return self._make_invitation(requested_email, requestor)
|
||||||
else:
|
else:
|
||||||
# if user already exists then just send an email
|
# if user already exists then just send an email
|
||||||
try:
|
try:
|
||||||
self._send_domain_invitation_email(requested_email, requestor, add_success=False)
|
self._send_domain_invitation_email(
|
||||||
|
requested_email, requestor, requested_user=requested_user, add_success=False
|
||||||
|
)
|
||||||
|
email_success = True
|
||||||
except EmailSendingError:
|
except EmailSendingError:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"Could not send email invitation (EmailSendingError)",
|
"Could not send email invitation (EmailSendingError)",
|
||||||
|
@ -876,6 +903,17 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
)
|
)
|
||||||
messages.warning(self.request, "Could not send email invitation.")
|
messages.warning(self.request, "Could not send email invitation.")
|
||||||
|
email_success = True
|
||||||
|
except OutsideOrgMemberError:
|
||||||
|
logger.warn(
|
||||||
|
"Could not send email. Can not invite member of a .gov organization to a different organization.",
|
||||||
|
self.object,
|
||||||
|
exc_info=True,
|
||||||
|
)
|
||||||
|
messages.error(
|
||||||
|
self.request,
|
||||||
|
f"{requested_email} is already a member of another .gov organization.",
|
||||||
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"Could not send email invitation (Other Exception)",
|
"Could not send email invitation (Other Exception)",
|
||||||
|
@ -883,17 +921,17 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
)
|
)
|
||||||
messages.warning(self.request, "Could not send email invitation.")
|
messages.warning(self.request, "Could not send email invitation.")
|
||||||
|
if email_success:
|
||||||
|
try:
|
||||||
|
UserDomainRole.objects.create(
|
||||||
|
user=requested_user,
|
||||||
|
domain=self.object,
|
||||||
|
role=UserDomainRole.Roles.MANAGER,
|
||||||
|
)
|
||||||
|
messages.success(self.request, f"Added user {requested_email}.")
|
||||||
|
except IntegrityError:
|
||||||
|
messages.warning(self.request, f"{requested_email} is already a manager for this domain")
|
||||||
|
|
||||||
try:
|
|
||||||
UserDomainRole.objects.create(
|
|
||||||
user=requested_user,
|
|
||||||
domain=self.object,
|
|
||||||
role=UserDomainRole.Roles.MANAGER,
|
|
||||||
)
|
|
||||||
except IntegrityError:
|
|
||||||
messages.warning(self.request, f"{requested_email} is already a manager for this domain")
|
|
||||||
else:
|
|
||||||
messages.success(self.request, f"Added user {requested_email}.")
|
|
||||||
return redirect(self.get_success_url())
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue