Skip to content

Commit 268d159

Browse files
authored
✨ Improvement: safer product setup (ITISFoundation#3395)
1 parent bbf7a85 commit 268d159

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

packages/models-library/src/models_library/basic_types.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from enum import Enum
22

3-
from pydantic import PositiveInt, conint, constr
3+
from pydantic import HttpUrl, PositiveInt, conint, constr
44

55
from .basic_regex import UUID_RE, VERSION_RE
66

@@ -26,6 +26,10 @@
2626
# auto-incremented primary-key IDs
2727
IdInt = PrimaryKeyInt = PositiveInt
2828

29+
# https e.g. https://techterms.com/definition/https
30+
class HttpSecureUrl(HttpUrl):
31+
allowed_schemes = {"https"}
32+
2933

3034
class LogLevel(str, Enum):
3135
DEBUG = "DEBUG"

services/web/server/src/simcore_service_webserver/products_db.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
PUBLIC_VARIABLE_NAME_RE,
1010
TWILIO_ALPHANUMERIC_SENDER_ID_RE,
1111
)
12+
from models_library.basic_types import HttpSecureUrl
1213
from models_library.utils.change_case import snake_to_camel
13-
from pydantic import BaseModel, Field, HttpUrl, validator
14+
from pydantic import BaseModel, EmailStr, Field, validator
1415
from simcore_postgres_database.models.products import jinja2_templates
1516

1617
from .db_base_repository import BaseRepository
@@ -23,6 +24,8 @@
2324
#
2425
# MODEL
2526
#
27+
28+
2629
class Product(BaseModel):
2730
"""
2831
Pydantic model associated to db_models.Products table
@@ -38,21 +41,21 @@ class Product(BaseModel):
3841
host_regex: Pattern
3942

4043
# EMAILS/PHONE
41-
support_email: str
44+
support_email: EmailStr
4245
twilio_messaging_sid: Optional[str] = Field(
4346
default=None,
4447
min_length=34,
4548
max_length=34,
4649
)
4750

4851
# MANUALS
49-
manual_url: HttpUrl
50-
manual_extra_url: Optional[HttpUrl] = None
52+
manual_url: HttpSecureUrl
53+
manual_extra_url: Optional[HttpSecureUrl] = None
5154

5255
# ISSUE TRACKER
53-
issues_login_url: Optional[HttpUrl] = None
54-
issues_new_url: Optional[HttpUrl] = None
55-
feedback_form_url: Optional[HttpUrl] = None
56+
issues_login_url: Optional[HttpSecureUrl] = None
57+
issues_new_url: Optional[HttpSecureUrl] = None
58+
feedback_form_url: Optional[HttpSecureUrl] = None
5659

5760
# TEMPLATES
5861
registration_email_template: Optional[str] = Field(
@@ -76,6 +79,18 @@ class Config:
7679
if c.server_default and isinstance(c.server_default.arg, str)
7780
},
7881
},
82+
# Example of data in the dabase with a url set with blanks
83+
{
84+
"name": "tis",
85+
"display_name": "TI PT",
86+
"short_name": "TIPI",
87+
"host_regex": r"(^tis[\.-])|(^ti-solutions\.)|(^ti-plan\.)",
88+
"support_email": "[email protected]",
89+
"manual_url": "https://foo.com",
90+
"issues_login_url": None,
91+
"issues_new_url": "https://foo.com/new",
92+
"feedback_form_url": "", # <-- blanks
93+
},
7994
]
8095
}
8196

@@ -88,6 +103,20 @@ def validate_name(cls, v):
88103
)
89104
return v
90105

106+
@validator(
107+
"manual_extra_url",
108+
"issues_login_url",
109+
"issues_new_url",
110+
"feedback_form_url",
111+
pre=True,
112+
)
113+
@classmethod
114+
def parse_empty_string_url_as_null(cls, v):
115+
"""Safe measure: database entries are sometimes left blank instead of null"""
116+
if isinstance(v, str) and len(v.strip()) == 0:
117+
return None
118+
return v
119+
91120
@property
92121
def twilio_alpha_numeric_sender_id(self) -> str:
93122
return self.short_name or self.display_name.replace(string.punctuation, "")[:11]

services/web/server/src/simcore_service_webserver/products_events.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ async def load_products_on_startup(app: web.Application):
5454
log.warning("Default front-end app is not in the products table")
5555

5656
app[APP_PRODUCTS_KEY] = app_products
57+
log.debug("Product loaded: %s", [p.name for p in app_products.values()])

0 commit comments

Comments
 (0)