Merge pull request #1435 from dod-ccpo/email-new-env-role
Email new env role
This commit is contained in:
commit
658e2cb9f1
@ -4,9 +4,12 @@ from typing import Dict, List, Optional
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from flask import current_app as app
|
|
||||||
from pydantic import BaseModel, validator, root_validator
|
from pydantic import BaseModel, validator, root_validator
|
||||||
|
|
||||||
|
from .utils import (
|
||||||
|
generate_mail_nickname,
|
||||||
|
generate_user_principal_name,
|
||||||
|
)
|
||||||
from atst.utils import snake_to_camel
|
from atst.utils import snake_to_camel
|
||||||
|
|
||||||
|
|
||||||
@ -527,11 +530,11 @@ class UserMixin(BaseModel):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def user_principal_name(self):
|
def user_principal_name(self):
|
||||||
return f"{self.mail_nickname}@{self.tenant_host_name}.{app.config.get('OFFICE_365_DOMAIN')}"
|
return generate_user_principal_name(self.display_name, self.tenant_host_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mail_nickname(self):
|
def mail_nickname(self):
|
||||||
return self.display_name.replace(" ", ".").lower()
|
return generate_mail_nickname(self.display_name)
|
||||||
|
|
||||||
@validator("password", pre=True, always=True)
|
@validator("password", pre=True, always=True)
|
||||||
def supply_password_default(cls, password):
|
def supply_password_default(cls, password):
|
||||||
|
10
atst/domain/csp/cloud/utils.py
Normal file
10
atst/domain/csp/cloud/utils.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from flask import current_app as app
|
||||||
|
|
||||||
|
|
||||||
|
def generate_user_principal_name(name, domain_name):
|
||||||
|
mail_name = generate_mail_nickname(name)
|
||||||
|
return f"{mail_name}@{domain_name}.{app.config.get('OFFICE_365_DOMAIN')}"
|
||||||
|
|
||||||
|
|
||||||
|
def generate_mail_nickname(name):
|
||||||
|
return name.replace(" ", ".").lower()
|
21
atst/jobs.py
21
atst/jobs.py
@ -7,6 +7,7 @@ from atst.database import db
|
|||||||
from atst.domain.application_roles import ApplicationRoles
|
from atst.domain.application_roles import ApplicationRoles
|
||||||
from atst.domain.applications import Applications
|
from atst.domain.applications import Applications
|
||||||
from atst.domain.csp.cloud import CloudProviderInterface
|
from atst.domain.csp.cloud import CloudProviderInterface
|
||||||
|
from atst.domain.csp.cloud.utils import generate_user_principal_name
|
||||||
from atst.domain.csp.cloud.exceptions import GeneralCSPException
|
from atst.domain.csp.cloud.exceptions import GeneralCSPException
|
||||||
from atst.domain.csp.cloud.models import (
|
from atst.domain.csp.cloud.models import (
|
||||||
ApplicationCSPPayload,
|
ApplicationCSPPayload,
|
||||||
@ -177,7 +178,21 @@ def do_create_environment_role(csp: CloudProviderInterface, environment_role_id=
|
|||||||
env_role.cloud_id = result.id
|
env_role.cloud_id = result.id
|
||||||
db.session.add(env_role)
|
db.session.add(env_role)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
# TODO: should send notification email to the user, maybe with their portal login name
|
|
||||||
|
user = env_role.application_role.user
|
||||||
|
domain_name = csp_details.get("domain_name")
|
||||||
|
username = generate_user_principal_name(user.full_name, domain_name,)
|
||||||
|
send_mail(
|
||||||
|
recipients=[user.email],
|
||||||
|
subject=translate("email.azure_account_update.subject"),
|
||||||
|
body=translate(
|
||||||
|
"email.azure_account_update.body",
|
||||||
|
{"url": app.config.get("AZURE_LOGIN_URL"), "username": username},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
app.logger.info(
|
||||||
|
f"Notification email sent for environment role creation. User id: {user.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def render_email(template_path, context):
|
def render_email(template_path, context):
|
||||||
@ -195,7 +210,7 @@ def send_PPOC_email(portfolio_dict):
|
|||||||
ppoc_email = portfolio_dict.get("password_recovery_email_address")
|
ppoc_email = portfolio_dict.get("password_recovery_email_address")
|
||||||
user_id = portfolio_dict.get("user_id")
|
user_id = portfolio_dict.get("user_id")
|
||||||
domain_name = portfolio_dict.get("domain_name")
|
domain_name = portfolio_dict.get("domain_name")
|
||||||
|
username = generate_user_principal_name(user_id, domain_name)
|
||||||
send_mail(
|
send_mail(
|
||||||
recipients=[ppoc_email],
|
recipients=[ppoc_email],
|
||||||
subject=translate("email.portfolio_ready.subject"),
|
subject=translate("email.portfolio_ready.subject"),
|
||||||
@ -203,7 +218,7 @@ def send_PPOC_email(portfolio_dict):
|
|||||||
"email.portfolio_ready.body",
|
"email.portfolio_ready.body",
|
||||||
{
|
{
|
||||||
"password_reset_address": app.config.get("AZURE_LOGIN_URL"),
|
"password_reset_address": app.config.get("AZURE_LOGIN_URL"),
|
||||||
"username": f"{user_id}@{domain_name}.{app.config.get('OFFICE_365_DOMAIN')}",
|
"username": username,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -12,10 +12,10 @@ from sqlalchemy_json import NestedMutableJson
|
|||||||
from atst.database import db
|
from atst.database import db
|
||||||
import atst.models.mixins as mixins
|
import atst.models.mixins as mixins
|
||||||
import atst.models.types as types
|
import atst.models.types as types
|
||||||
|
from atst.domain.csp.cloud.utils import generate_mail_nickname
|
||||||
from atst.domain.permission_sets import PermissionSets
|
from atst.domain.permission_sets import PermissionSets
|
||||||
from atst.models.base import Base
|
from atst.models.base import Base
|
||||||
from atst.models.portfolio_role import PortfolioRole
|
from atst.models.portfolio_role import PortfolioRole, Status as PortfolioRoleStatus
|
||||||
from atst.models.portfolio_role import Status as PortfolioRoleStatus
|
|
||||||
from atst.utils import first_or_none
|
from atst.utils import first_or_none
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ class Portfolio(
|
|||||||
@property
|
@property
|
||||||
def domain_name(self):
|
def domain_name(self):
|
||||||
"""
|
"""
|
||||||
CSP domain name associated with portfolio.
|
CSP domain name associated with portfolio.
|
||||||
If a domain name is not set, generate one.
|
If a domain name is not set, generate one.
|
||||||
"""
|
"""
|
||||||
domain_name = re.sub("[^0-9a-zA-Z]+", "", self.name).lower() + "".join(
|
domain_name = re.sub("[^0-9a-zA-Z]+", "", self.name).lower() + "".join(
|
||||||
@ -205,7 +205,9 @@ class Portfolio(
|
|||||||
|
|
||||||
def to_dictionary(self):
|
def to_dictionary(self):
|
||||||
return {
|
return {
|
||||||
"user_id": f"{self.owner.first_name[0]}{self.owner.last_name}".lower(),
|
"user_id": generate_mail_nickname(
|
||||||
|
f"{self.owner.first_name[0]}{self.owner.last_name}"
|
||||||
|
),
|
||||||
"password": "",
|
"password": "",
|
||||||
"domain_name": self.domain_name,
|
"domain_name": self.domain_name,
|
||||||
"first_name": self.owner.first_name,
|
"first_name": self.owner.first_name,
|
||||||
|
@ -399,23 +399,35 @@ def test_dispatch_create_environment_role(monkeypatch):
|
|||||||
mock.delay.assert_called_once_with(environment_role_id=env_role.id)
|
mock.delay.assert_called_once_with(environment_role_id=env_role.id)
|
||||||
|
|
||||||
|
|
||||||
def test_create_environment_role():
|
class TestCreateEnvironmentRole:
|
||||||
portfolio = PortfolioFactory.create(csp_data={"tenant_id": "123"})
|
@pytest.fixture
|
||||||
app = ApplicationFactory.create(portfolio=portfolio)
|
def env_role(self):
|
||||||
app_role = ApplicationRoleFactory.create(
|
portfolio = PortfolioFactory.create(csp_data={"tenant_id": "123"})
|
||||||
application=app, status=ApplicationRoleStatus.ACTIVE, cloud_id="123",
|
app = ApplicationFactory.create(portfolio=portfolio)
|
||||||
)
|
app_role = ApplicationRoleFactory.create(
|
||||||
env = EnvironmentFactory.create(application=app, cloud_id="123")
|
application=app, status=ApplicationRoleStatus.ACTIVE, cloud_id="123",
|
||||||
env_role = EnvironmentRoleFactory.create(
|
)
|
||||||
environment=env, application_role=app_role, cloud_id=None
|
env = EnvironmentFactory.create(application=app, cloud_id="123")
|
||||||
)
|
return EnvironmentRoleFactory.create(
|
||||||
|
environment=env, application_role=app_role, cloud_id=None
|
||||||
|
)
|
||||||
|
|
||||||
csp = Mock()
|
@pytest.fixture
|
||||||
result = UserRoleCSPResult(id="a-cloud-id")
|
def csp(self):
|
||||||
csp.create_user_role = MagicMock(return_value=result)
|
csp = Mock()
|
||||||
do_create_environment_role(csp, environment_role_id=env_role.id)
|
result = UserRoleCSPResult(id="a-cloud-id")
|
||||||
|
csp.create_user_role = MagicMock(return_value=result)
|
||||||
|
return csp
|
||||||
|
|
||||||
assert env_role.cloud_id == "a-cloud-id"
|
def test_success(self, env_role, csp):
|
||||||
|
do_create_environment_role(csp, environment_role_id=env_role.id)
|
||||||
|
assert env_role.cloud_id == "a-cloud-id"
|
||||||
|
|
||||||
|
def test_sends_email(self, monkeypatch, env_role, csp):
|
||||||
|
send_mail = Mock()
|
||||||
|
monkeypatch.setattr("atst.jobs.send_mail", send_mail)
|
||||||
|
do_create_environment_role(csp, environment_role_id=env_role.id)
|
||||||
|
assert send_mail.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
class TestSendTaskOrderFiles:
|
class TestSendTaskOrderFiles:
|
||||||
|
@ -86,7 +86,10 @@ email:
|
|||||||
app_role_created:
|
app_role_created:
|
||||||
subject: Application Role Created
|
subject: Application Role Created
|
||||||
body: "Your application role has been created.\nVisit {url}, and use your username, {username}, to log in."
|
body: "Your application role has been created.\nVisit {url}, and use your username, {username}, to log in."
|
||||||
portfolio_invite: "{inviter_name} has invited you to a JEDI cloud portfolio."
|
azure_account_update:
|
||||||
|
subject: Azure account update
|
||||||
|
body: "There has been an update to your Azure account. \nVisit {url}, and use your username, {username}, to log in."
|
||||||
|
portfolio_invite: "{inviter_name} has invited you to a JEDI cloud portfolio"
|
||||||
portfolio_ready:
|
portfolio_ready:
|
||||||
subject: Portfolio Provisioned
|
subject: Portfolio Provisioned
|
||||||
body: "Your portfolio has been provisioned.\nVisit {password_reset_address}, and use your username, {username}, to create a password."
|
body: "Your portfolio has been provisioned.\nVisit {password_reset_address}, and use your username, {username}, to create a password."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user