Skip to content

Commit

Permalink
✨ Is829/jlab login required (#4001)
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov authored Mar 21, 2023
1 parent ef19c77 commit 4e7ecc4
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class ProjectType(enum.Enum):
sa.Boolean,
nullable=False,
default=False,
doc="If true, the project is publicaly accessible via the studies dispatcher",
doc="If true, the project is publicaly accessible via the studies dispatcher (i.e. no registration required)",
),
sa.Column(
"hidden",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,12 @@ async def _get_project(
sa.text(
f"jsonb_exists_any(projects.access_rights, {assemble_array_groups(user_groups)})"
),
sa.case(
[
(
only_published,
projects.c.published == "true",
)
],
else_=True,
),
),
)

if only_published:
conditions &= projects.c.published == "true"

query = select([projects]).where(conditions)
if for_update:
query = query.with_for_update()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
from typing import Final

# NOTE: MSG_* strings MUST be human readable messages
# NOTE: MSG_$(ERROR_CODE_NAME) strings MUST be human readable messages

MSG_PROJECT_NOT_FOUND: Final[str] = "Cannot find any study with ID '{project_id}'."

MSG_PROJECT_NOT_FOUND: Final[str] = "Cannot find any study with ID '{project_id}'"

MSG_PROJECT_NOT_PUBLISHED: Final[
str
] = "Cannot find any published study with ID '{project_id}'"

# This error happens when the linked study ID does not exists OR is not shared with everyone
MSG_PROJECT_NOT_PUBLISHED: Final[str] = "Cannot find any study with ID '{project_id}'"

# This error happens when the linked study ID does not exists OR is not shared with everyone OR is NOT public
MSG_PUBLIC_PROJECT_NOT_PUBLISHED: Final[str] = (
"You need to be logged in to access study with ID '{project_id}'\n"
"Please login and try again\n"
"If you don't have an account, write to the Support email to request one\n"
)


MSG_UNEXPECTED_ERROR: Final[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from ._constants import (
MSG_PROJECT_NOT_FOUND,
MSG_PROJECT_NOT_PUBLISHED,
MSG_PUBLIC_PROJECT_NOT_PUBLISHED,
MSG_UNEXPECTED_ERROR,
)
from .settings import StudiesDispatcherSettings, get_plugin_settings
Expand All @@ -62,21 +63,26 @@ def _compose_uuid(template_uuid, user_id, query="") -> str:


async def _get_published_template_project(
app: web.Application, project_uuid: str
app: web.Application,
project_uuid: str,
*,
is_user_authenticated: bool,
) -> ProjectDict:
"""
raises RedirectToFrontEndPageError
"""
db = ProjectDBAPI.get_from_app_context(app)

only_public_projects = not is_user_authenticated

try:
prj, _ = await db.get_project(
project_uuid=project_uuid,
# NOTE: these are the conditions for a published study
# 1. MUST be a template
only_templates=True,
# 2. MUST be checked for publication
only_published=True,
# 2. If user is unauthenticated, then MUST be public
only_published=only_public_projects,
# 3. MUST be shared with EVERYONE=1 in read mode, i.e.
user_id=ANY_USER, # any user
check_permissions="read", # any user has read access
Expand All @@ -89,11 +95,19 @@ async def _get_published_template_project(

except (ProjectNotFoundError, ProjectInvalidRightsError) as err:
log.debug(
"Requested project with %s is not published. Reason: %s",
"Project with %s %s was not found. Reason: %s",
f"{project_uuid=}",
f"{only_public_projects=}",
err.detailed_message(),
)

if only_public_projects:
raise RedirectToFrontEndPageError(
MSG_PUBLIC_PROJECT_NOT_PUBLISHED.format(project_id=project_uuid),
error_code="PUBLIC_PROJECT_NOT_PUBLISHED",
status_code=web.HTTPNotFound.status_code,
) from err

raise RedirectToFrontEndPageError(
MSG_PROJECT_NOT_PUBLISHED.format(project_id=project_uuid),
error_code="PROJECT_NOT_PUBLISHED",
Expand Down Expand Up @@ -295,10 +309,13 @@ async def wrapper(request: web.Request) -> web.StreamResponse:
f"{error_code}",
extra={"error_code": error_code},
)
raise RedirectToFrontEndPageError(
MSG_UNEXPECTED_ERROR.format(hint=""),
error_code=error_code,
status_code=web.HTTPInternalServerError.status_code,
raise create_redirect_response(
request.app,
page="error",
message=compose_support_error_msg(
msg=MSG_UNEXPECTED_ERROR.format(hint=""), error_code=error_code
),
status_code=500,
) from err

return wrapper
Expand All @@ -316,16 +333,21 @@ async def get_redirection_to_study_page(request: web.Request) -> web.Response:
project_id = request.match_info["id"]
assert request.app.router[INDEX_RESOURCE_NAME] # nosec

# Get published PROJECT referenced in link
template_project = await _get_published_template_project(request.app, project_id)

# Get or create a valid USER
# Checks USER
user = None
is_anonymous_user = await is_anonymous(request)
if not is_anonymous_user:
# NOTE: covers valid cookie with unauthorized user (e.g. expired guest/banned)
user = await get_authorized_user(request)

# Get published PROJECT referenced in link
template_project = await _get_published_template_project(
request.app,
project_id,
is_user_authenticated=bool(user),
)

# Get or create a valid USER
if not user:
log.debug("Creating temporary user ...")
user = await _create_temporary_user(request)
Expand Down
12 changes: 9 additions & 3 deletions services/web/server/src/simcore_service_webserver/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,17 @@ def get_tracemalloc_info(top=10) -> list[str]:
def compose_support_error_msg(
msg: str, error_code: ErrorCodeStr, support_email: str = "support"
) -> str:
return (
f"{msg.strip(' .').capitalize()} [{error_code}].\n"
f"Please contact {support_email} and attach the message above"
sentences = []
for line in msg.split("\n"):
if sentence := line.strip(" ."):
sentences.append(sentence[0].upper() + sentence[1:])

sentences.append(
f"For more information please forward this message to {support_email} [{error_code}]"
)

return ". ".join(sentences)


# -----------------------------------------------
#
Expand Down
17 changes: 15 additions & 2 deletions services/web/server/tests/unit/isolated/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import urllib.parse
from contextlib import contextmanager
from datetime import datetime
from typing import Dict
from urllib.parse import unquote_plus

import pytest
import yarl
from simcore_service_webserver.utils import (
DATETIME_FORMAT,
compose_support_error_msg,
compute_sha1_on_small_dataset,
now_str,
to_datetime,
Expand Down Expand Up @@ -75,7 +75,7 @@ def test_yarl_url_compose_changed_with_latest_release():


@pytest.mark.skip(reason="DEV-demo")
async def test_compute_sha1_on_small_dataset(fake_project: Dict):
async def test_compute_sha1_on_small_dataset(fake_project: dict):
# Based on GitHK review https://github.com/ITISFoundation/osparc-simcore/pull/2556:
# From what I know, these having function tend to be a bit CPU intensive, based on the size of the dataset.
# Could we maybe have an async version of this function here, run it on an executor?
Expand Down Expand Up @@ -126,3 +126,16 @@ def timeit_ctx(what):

# For larger datasets, async solution definitvely scales better
# but for smaller ones, the overhead is considerable


def test_compose_support_error_msg():

msg = compose_support_error_msg(
"first sentence for Mr.X \n Second sentence.",
error_code="OEC:139641204989600",
support_email="[email protected]",
)
assert (
msg == "First sentence for Mr.X. Second sentence."
" For more information please forward this message to [email protected] [OEC:139641204989600]"
)
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ async def published_project(
project_data = deepcopy(fake_project)
project_data["name"] = "Published project"
project_data["uuid"] = "e2e38eee-c569-4e55-b104-70d159e49c87"
project_data["published"] = True # OPENED
project_data["published"] = True # PUBLIC
project_data["access_rights"] = {
# everyone HAS read access
"1": {"read": True, "write": False, "delete": False}
Expand Down

0 comments on commit 4e7ecc4

Please sign in to comment.