Skip to content

Commit a9703a5

Browse files
authored
🎨 New front-end statics (ITISFoundation#5534)
1 parent 531a211 commit a9703a5

File tree

10 files changed

+53
-35
lines changed

10 files changed

+53
-35
lines changed

‎.env-devel‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ S3_EXPORT_SECURE=0
150150
SCICRUNCH_API_BASE_URL=https://scicrunch.org/api/1
151151
SCICRUNCH_API_KEY=REPLACE_ME_with_valid_api_key
152152

153+
SIMCORE_VCS_RELEASE_TAG=latest
154+
153155
SMTP_HOST=fake.mail.server.com
154156
SMTP_PORT=25
155157
SMTP_USERNAME=it_doesnt_matter

‎services/docker-compose.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,8 @@ services:
624624

625625
WEBSERVER_STATICWEB: ${WEBSERVER_STATICWEB}
626626

627+
SIMCORE_VCS_RELEASE_TAG: ${SIMCORE_VCS_RELEASE_TAG}
628+
627629
# WEBSERVER_STORAGE
628630
STORAGE_ENDPOINT: ${STORAGE_ENDPOINT}
629631
STORAGE_HOST: ${STORAGE_HOST}

‎services/static-webserver/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Used for static content serving.
44

5-
### Furtherr steps
5+
## Further steps
66

77
In the future will fully serve all static content. Currently the `webserver` is still serving the following routes:
88

‎services/static-webserver/client/source/class/osparc/po/Users.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ qx.Class.define("osparc.po.Users", {
6363

6464
const userEmail = new qx.ui.form.TextField().set({
6565
required: true,
66-
placeholder: this.tr("new.[email protected]")
66+
placeholder: this.tr("[email protected] or user@*")
6767
});
6868
form.add(userEmail, this.tr("Email"));
6969

‎services/web/server/src/simcore_service_webserver/application_settings.py‎

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import logging
2-
from datetime import datetime
32
from functools import cached_property
4-
from typing import Any
3+
from typing import Any, Final
54

65
from aiohttp import web
76
from models_library.basic_types import (
@@ -85,10 +84,7 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
8584
description="Name of the tag that makrs this release or None if undefined",
8685
example="ResistanceIsFutile10",
8786
)
88-
SIMCORE_VCS_RELEASE_DATE: datetime | None = Field(
89-
default=None,
90-
description="Release date or None if undefined. It corresponds to the tag's creation date",
91-
)
87+
9288
SIMCORE_VCS_RELEASE_URL: AnyHttpUrl | None = Field(
9389
default=None,
9490
description="URL to release notes",
@@ -243,13 +239,18 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
243239
@root_validator()
244240
@classmethod
245241
def build_vcs_release_url_if_unset(cls, values):
246-
vcs_release_url = values.get("SIMCORE_VCS_RELEASE_URL")
242+
release_url = values.get("SIMCORE_VCS_RELEASE_URL")
247243

248-
if vcs_release_url is None and (
244+
if release_url is None and (
249245
vsc_release_tag := values.get("SIMCORE_VCS_RELEASE_TAG")
250246
):
251-
vcs_release_url = f"https://github.com/ITISFoundation/osparc-simcore/releases/tag/{vsc_release_tag}"
252-
values["SIMCORE_VCS_RELEASE_URL"] = vcs_release_url
247+
if vsc_release_tag == "latest":
248+
release_url = (
249+
"https://github.com/ITISFoundation/osparc-simcore/commits/master/"
250+
)
251+
else:
252+
release_url = f"https://github.com/ITISFoundation/osparc-simcore/releases/tag/{vsc_release_tag}"
253+
values["SIMCORE_VCS_RELEASE_URL"] = release_url
253254

254255
return values
255256

@@ -309,19 +310,15 @@ def _get_disabled_public_plugins(self) -> list[str]:
309310
# might reveal critical info on the settings of a deploy to the client.
310311
# TODO: more reliable definition of a "plugin" and whether it can be advertised or not
311312
# (extra var? e.g. Field( ... , x_advertise_plugin=True))
312-
PUBLIC_PLUGIN_CANDIDATES = {
313+
public_plugin_candidates: Final = {
313314
"WEBSERVER_CLUSTERS",
314315
"WEBSERVER_EXPORTER",
315316
"WEBSERVER_META_MODELING",
316317
"WEBSERVER_PAYMENTS",
317318
"WEBSERVER_SCICRUNCH",
318319
"WEBSERVER_VERSION_CONTROL",
319320
}
320-
return [
321-
plugin_name
322-
for plugin_name in PUBLIC_PLUGIN_CANDIDATES
323-
if not self.is_enabled(plugin_name)
324-
]
321+
return [_ for _ in public_plugin_candidates if not self.is_enabled(_)]
325322

326323
def _export_by_alias(self, **kwargs) -> dict[str, Any]:
327324
# This is a small helper to assist export functions since aliases are no longer used by
@@ -337,7 +334,6 @@ def _export_by_alias(self, **kwargs) -> dict[str, Any]:
337334
"SC_VCS_REF": "vcs_ref",
338335
"SC_VCS_URL": "vcs_url",
339336
"SIMCORE_VCS_RELEASE_TAG": "vcs_release_tag",
340-
"SIMCORE_VCS_RELEASE_DATE": "vcs_release_date",
341337
"SIMCORE_VCS_RELEASE_URL": "vcs_release_url",
342338
"SWARM_STACK_NAME": "stack_name",
343339
}
@@ -366,7 +362,6 @@ def public_dict(self) -> dict[str, Any]:
366362
"SC_VCS_REF",
367363
"SC_VCS_URL",
368364
"SIMCORE_VCS_RELEASE_TAG",
369-
"SIMCORE_VCS_RELEASE_DATE",
370365
"SIMCORE_VCS_RELEASE_URL",
371366
},
372367
exclude_none=True,
@@ -383,11 +378,11 @@ def to_client_statics(self) -> dict[str, Any]:
383378
"SC_VCS_REF": True,
384379
"SC_VCS_URL": True,
385380
"SIMCORE_VCS_RELEASE_TAG": True,
386-
"SIMCORE_VCS_RELEASE_DATE": True,
387381
"SIMCORE_VCS_RELEASE_URL": True,
388382
"SWARM_STACK_NAME": True,
389383
"WEBSERVER_PROJECTS": {"PROJECTS_MAX_NUM_RUNNING_DYNAMIC_NODES"},
390384
"WEBSERVER_LOGIN": {"LOGIN_ACCOUNT_DELETION_RETENTION_DAYS"},
385+
"WEBSERVER_SESSION": {"SESSION_COOKIE_MAX_AGE"},
391386
},
392387
exclude_none=True,
393388
)

‎services/web/server/src/simcore_service_webserver/users/_api.py‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,19 @@ async def set_user_as_deleted(app: web.Application, user_id: UserID) -> None:
6262
)
6363

6464

65+
def _glob_to_sql_like(glob_pattern: str) -> str:
66+
# Escape SQL LIKE special characters in the glob pattern
67+
sql_like_pattern = glob_pattern.replace("%", r"\%").replace("_", r"\_")
68+
# Convert glob wildcards to SQL LIKE wildcards
69+
return sql_like_pattern.replace("*", "%").replace("?", "_")
70+
71+
6572
async def search_users(
66-
app: web.Application, email_like: str, *, include_products: bool = False
73+
app: web.Application, email_glob: str, *, include_products: bool = False
6774
) -> list[_schemas.UserProfile]:
6875
# NOTE: this search is deploy-wide i.e. independent of the product!
6976
rows = await _db.search_users_and_get_profile(
70-
get_database_engine(app), email_like=email_like
77+
get_database_engine(app), email_like=_glob_to_sql_like(email_glob)
7178
)
7279

7380
async def _list_products_or_none(user_id):
@@ -105,7 +112,7 @@ async def pre_register_user(
105112
app: web.Application, profile: _schemas.PreUserProfile, creator_user_id: UserID
106113
) -> _schemas.UserProfile:
107114

108-
found = await search_users(app, email_like=profile.email, include_products=False)
115+
found = await search_users(app, email_glob=profile.email, include_products=False)
109116
if found:
110117
raise AlreadyPreRegisteredError(num_found=len(found), email=profile.email)
111118

@@ -136,7 +143,7 @@ async def pre_register_user(
136143
**details,
137144
)
138145

139-
found = await search_users(app, email_like=profile.email, include_products=False)
146+
found = await search_users(app, email_glob=profile.email, include_products=False)
140147

141148
assert len(found) == 1 # nosec
142149
return found[0]

‎services/web/server/src/simcore_service_webserver/users/_handlers.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ async def update_my_profile(request: web.Request) -> web.Response:
7171

7272

7373
class _SearchQueryParams(BaseModel):
74-
email: str = Field(min_length=3, max_length=200)
74+
email: str = Field(
75+
min_length=3,
76+
max_length=200,
77+
description="complete or glob pattern for an email",
78+
)
7579

7680

7781
_RESPONSE_MODEL_MINIMAL_POLICY = RESPONSE_MODEL_POLICY.copy()
@@ -89,7 +93,7 @@ async def search_users(request: web.Request) -> web.Response:
8993
query_params = parse_request_query_parameters_as(_SearchQueryParams, request)
9094

9195
found = await _api.search_users(
92-
request.app, email_like=query_params.email, include_products=True
96+
request.app, email_glob=query_params.email, include_products=True
9397
)
9498

9599
return envelope_json_response(

‎services/web/server/tests/unit/isolated/conftest.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def app_config_for_production_legacy(test_data_dir: Path) -> ConfigDict:
7575

7676

7777
@pytest.fixture
78-
def mock_env_auto_deployer_agent(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict:
78+
def mock_env_deployer_pipeline(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict:
7979
# git log --tags --simplify-by-decoration --pretty="format:%ci %d"
8080
# 2023-02-08 18:34:56 +0000 (tag: v1.47.0, tag: staging_ResistanceIsFutile12)
8181
# 2023-02-06 18:40:07 +0100 (tag: v1.46.0, tag: staging_ResistanceIsFutile11)
@@ -85,7 +85,6 @@ def mock_env_auto_deployer_agent(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict
8585
monkeypatch,
8686
envs={
8787
"SIMCORE_VCS_RELEASE_TAG": "staging_ResistanceIsFutile12",
88-
"SIMCORE_VCS_RELEASE_DATE": "2023-02-10T18:03:35.957601",
8988
},
9089
)
9190

‎services/web/server/tests/unit/isolated/test_application_settings.py‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import pytest
99
from aiohttp import web
10+
from pydantic import HttpUrl, parse_obj_as
1011
from pytest_simcore.helpers.typing_env import EnvVarsDict
1112
from pytest_simcore.helpers.utils_envs import setenvs_from_dict, setenvs_from_envfile
1213
from servicelib.json_serialization import json_dumps
@@ -60,7 +61,7 @@ def mock_env_makefile(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict:
6061

6162

6263
@pytest.fixture
63-
def mock_env_Dockerfile_build(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict:
64+
def mock_env_dockerfile_build(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict:
6465
#
6566
# docker run -it --hostname "{{.Node.Hostname}}-{{.Service.Name}}-{{.Task.Slot}}" local/webserver:production printenv
6667
#
@@ -100,8 +101,8 @@ def mock_webserver_service_environment(
100101
monkeypatch: pytest.MonkeyPatch,
101102
mock_env_makefile: EnvVarsDict,
102103
mock_env_devel_environment: EnvVarsDict,
103-
mock_env_Dockerfile_build: EnvVarsDict,
104-
mock_env_auto_deployer_agent: EnvVarsDict,
104+
mock_env_dockerfile_build: EnvVarsDict,
105+
mock_env_deployer_pipeline: EnvVarsDict,
105106
) -> EnvVarsDict:
106107
"""
107108
Mocks environment produce in the docker compose config with a .env (.env-devel)
@@ -144,14 +145,15 @@ def mock_webserver_service_environment(
144145
"STORAGE_PORT": os.environ.get("STORAGE_PORT", "8080"),
145146
"SWARM_STACK_NAME": os.environ.get("SWARM_STACK_NAME", "simcore"),
146147
"WEBSERVER_LOGLEVEL": os.environ.get("LOG_LEVEL", "WARNING"),
148+
"SESSION_COOKIE_MAX_AGE": str(7 * 24 * 60 * 60),
147149
},
148150
)
149151

150152
return (
151153
mock_env_makefile
152154
| mock_env_devel_environment
153-
| mock_env_Dockerfile_build
154-
| mock_env_auto_deployer_agent
155+
| mock_env_dockerfile_build
156+
| mock_env_deployer_pipeline
155157
| mock_envs_docker_compose_environment
156158
)
157159

@@ -224,6 +226,13 @@ def test_settings_to_client_statics_plugins(
224226
statics["webserverLogin"]["LOGIN_ACCOUNT_DELETION_RETENTION_DAYS"]
225227
== settings.WEBSERVER_LOGIN.LOGIN_ACCOUNT_DELETION_RETENTION_DAYS
226228
)
229+
assert (
230+
statics["webserverSession"].get("SESSION_COOKIE_MAX_AGE")
231+
== settings.WEBSERVER_SESSION.SESSION_COOKIE_MAX_AGE
232+
)
233+
234+
assert statics["vcsReleaseTag"]
235+
assert parse_obj_as(HttpUrl, statics["vcsReleaseUrl"])
227236

228237
assert set(statics["pluginsDisabled"]) == (disable_plugins | {"WEBSERVER_CLUSTERS"})
229238

‎services/web/server/tests/unit/isolated/test_rest.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def client(
2727
aiohttp_client: Callable,
2828
api_version_prefix: str,
2929
mock_env_devel_environment: EnvVarsDict,
30-
mock_env_auto_deployer_agent: EnvVarsDict,
30+
mock_env_deployer_pipeline: EnvVarsDict,
3131
) -> TestClient:
3232
app = create_safe_application()
3333

0 commit comments

Comments
 (0)