From 2a5739d0a7eec5e565a90a2b5a0c4a7b42b90c77 Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Wed, 29 Jan 2025 10:59:45 +0100 Subject: [PATCH 1/5] PO email in product --- .../login/_registration_api.py | 8 ++++---- .../products/_model.py | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/services/web/server/src/simcore_service_webserver/login/_registration_api.py b/services/web/server/src/simcore_service_webserver/login/_registration_api.py index 22252f2dc864..b35040f85360 100644 --- a/services/web/server/src/simcore_service_webserver/login/_registration_api.py +++ b/services/web/server/src/simcore_service_webserver/login/_registration_api.py @@ -63,7 +63,7 @@ async def send_account_request_email_to_support( ipinfo: dict, ): template_name = "request_account.jinja2" - support_email = product.support_email + destination_email = product.product_owners_email or product.support_email email_template_path = await get_product_template_path(request, template_name) try: user_email = TypeAdapter(LowerCaseEmailStr).validate_python( @@ -75,8 +75,8 @@ async def send_account_request_email_to_support( try: await send_email_from_template( request, - from_=support_email, - to=support_email, + from_=product.support_email, + to=destination_email, reply_to=user_email, # So that issue-tracker system ACK email is sent to the user that requests the account template=email_template_path, context={ @@ -99,7 +99,7 @@ async def send_account_request_email_to_support( _logger.exception( "Failed while sending '%s' email to %s", template_name, - f"{support_email=}", + f"{destination_email=}", ) diff --git a/services/web/server/src/simcore_service_webserver/products/_model.py b/services/web/server/src/simcore_service_webserver/products/_model.py index 5a00687b1a7b..ef4b7f9498cd 100644 --- a/services/web/server/src/simcore_service_webserver/products/_model.py +++ b/services/web/server/src/simcore_service_webserver/products/_model.py @@ -63,11 +63,18 @@ class Product(BaseModel): ..., description="Host regex" ) - support_email: LowerCaseEmailStr = Field( - ..., - description="Main support email." - " Other support emails can be defined under 'support' field", - ) + support_email: Annotated[ + LowerCaseEmailStr, + Field( + description="Main support email." + " Other support emails can be defined under 'support' field", + ), + ] + + product_owners_email: Annotated[ + LowerCaseEmailStr | None, + Field(description="Used e.g. for account requests forms"), + ] = None twilio_messaging_sid: str | None = Field( default=None, min_length=34, max_length=34, description="Identifier for SMS" From f96313b31df0f6e437a2250c8b0f350fa91be7e5 Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:04:08 +0100 Subject: [PATCH 2/5] new column --- .../src/simcore_postgres_database/models/products.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/postgres-database/src/simcore_postgres_database/models/products.py b/packages/postgres-database/src/simcore_postgres_database/models/products.py index 344326fbf488..8a1dd8cf29e9 100644 --- a/packages/postgres-database/src/simcore_postgres_database/models/products.py +++ b/packages/postgres-database/src/simcore_postgres_database/models/products.py @@ -154,6 +154,12 @@ class ProductLoginSettingsDict(TypedDict, total=False): doc="Support email for this product" 'Therefore smtp_sender = f"{display_name} support <{support_email}>"', ), + sa.Column( + "product_owners_email", + sa.String, + nullable=True, + doc="Alternative support email directed to POs only (e.g. for account request, sales, etc)", + ), sa.Column( "twilio_messaging_sid", sa.String, From 81568d336542cceb36c258899d2ab7ca36c22f36 Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:06:11 +0100 Subject: [PATCH 3/5] migration --- ...c517536e0a_add_product_owners_email_col.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 packages/postgres-database/src/simcore_postgres_database/migration/versions/1bc517536e0a_add_product_owners_email_col.py diff --git a/packages/postgres-database/src/simcore_postgres_database/migration/versions/1bc517536e0a_add_product_owners_email_col.py b/packages/postgres-database/src/simcore_postgres_database/migration/versions/1bc517536e0a_add_product_owners_email_col.py new file mode 100644 index 000000000000..7d6f45919e4c --- /dev/null +++ b/packages/postgres-database/src/simcore_postgres_database/migration/versions/1bc517536e0a_add_product_owners_email_col.py @@ -0,0 +1,29 @@ +"""Add product owners email col + +Revision ID: 1bc517536e0a +Revises: 5f88b513cd4c +Create Date: 2025-01-29 10:05:58.254306+00:00 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "1bc517536e0a" +down_revision = "5f88b513cd4c" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "products", sa.Column("product_owners_email", sa.String(), nullable=True) + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("products", "product_owners_email") + # ### end Alembic commands ### From c769b23b0a731155e3dff9285fee42e661bcee85 Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:15:14 +0100 Subject: [PATCH 4/5] minor --- .../src/pytest_simcore/helpers/faker_factories.py | 1 + .../src/simcore_service_webserver/login/_registration_api.py | 2 +- .../unit/with_dbs/03/login/test_login_registration_handlers.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py b/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py index 803987b3b8af..c9384c3873d0 100644 --- a/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py +++ b/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py @@ -227,6 +227,7 @@ def random_product( "short_name": suffix[:4], "host_regex": r"[a-zA-Z0-9]+\.com", "support_email": f"support@{suffix}.io", + "product_owners_email": fake.random_element(elements=[fake.email(), None]), "twilio_messaging_sid": fake.random_element(elements=(None, fake.uuid4()[:34])), "vendor": Vendor( name=fake.company(), diff --git a/services/web/server/src/simcore_service_webserver/login/_registration_api.py b/services/web/server/src/simcore_service_webserver/login/_registration_api.py index b35040f85360..2d5389426809 100644 --- a/services/web/server/src/simcore_service_webserver/login/_registration_api.py +++ b/services/web/server/src/simcore_service_webserver/login/_registration_api.py @@ -81,7 +81,7 @@ async def send_account_request_email_to_support( template=email_template_path, context={ "host": request.host, - "name": "support-team", + "name": "product-owners", "product": product.model_dump( include={ "name", diff --git a/services/web/server/tests/unit/with_dbs/03/login/test_login_registration_handlers.py b/services/web/server/tests/unit/with_dbs/03/login/test_login_registration_handlers.py index 655afde42b72..03b543e90383 100644 --- a/services/web/server/tests/unit/with_dbs/03/login/test_login_registration_handlers.py +++ b/services/web/server/tests/unit/with_dbs/03/login/test_login_registration_handlers.py @@ -208,4 +208,4 @@ async def test_request_an_account( mimetext = mocked_send_email.call_args[1]["message"] assert "account" in mimetext["Subject"].lower() assert mimetext["From"] == product.support_email - assert mimetext["To"] == product.support_email + assert mimetext["To"] == product.product_owners_email or product.support_email From e3f5899d1f885529c293d801b1a68064b95dc806 Mon Sep 17 00:00:00 2001 From: Pedro Crespo-Valero <32402063+pcrespov@users.noreply.github.com> Date: Wed, 29 Jan 2025 11:19:39 +0100 Subject: [PATCH 5/5] binds db --- .../src/pytest_simcore/helpers/faker_factories.py | 8 ++++++-- .../server/src/simcore_service_webserver/products/_db.py | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py b/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py index c9384c3873d0..ce7c5685e940 100644 --- a/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py +++ b/packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py @@ -227,8 +227,12 @@ def random_product( "short_name": suffix[:4], "host_regex": r"[a-zA-Z0-9]+\.com", "support_email": f"support@{suffix}.io", - "product_owners_email": fake.random_element(elements=[fake.email(), None]), - "twilio_messaging_sid": fake.random_element(elements=(None, fake.uuid4()[:34])), + "product_owners_email": fake.random_element( + elements=[f"product-onwers@{suffix}.io", None] + ), + "twilio_messaging_sid": fake.random_element( + elements=(None, f"{fake.uuid4()}"[:34]) + ), "vendor": Vendor( name=fake.company(), copyright=fake.company_suffix(), diff --git a/services/web/server/src/simcore_service_webserver/products/_db.py b/services/web/server/src/simcore_service_webserver/products/_db.py index d0317fdc61b1..a59f6077dfca 100644 --- a/services/web/server/src/simcore_service_webserver/products/_db.py +++ b/services/web/server/src/simcore_service_webserver/products/_db.py @@ -32,6 +32,7 @@ products.c.short_name, products.c.host_regex, products.c.support_email, + products.c.product_owners_email, products.c.twilio_messaging_sid, products.c.vendor, products.c.issues,