diff --git a/.github/prompts/update-user-messages.prompt.md b/.github/prompts/update-user-messages.prompt.md
index 66f9e464f3c..37eee04951b 100644
--- a/.github/prompts/update-user-messages.prompt.md
+++ b/.github/prompts/update-user-messages.prompt.md
@@ -18,7 +18,7 @@ error_msg = user_message("Operation failed. Please try again later.")
## Guidelines for Updating User Messages
-When modifying user messages, follow these rules:
+When modifying user messages, follow **as close as possible** these rules:
1. **Version Tracking**: Every modification to a user message must include an incremented `_version` parameter:
@@ -43,7 +43,7 @@ When modifying user messages, follow these rules:
user_message("Unable to load project.", _version=1)
```
-3. **Message Style**: Follow *strictly* the guidelines in `${workspaceFolder}/docs/user-messages-guidelines.md`
+3. **Message Style**: Follow **strictly** the guidelines in `${workspaceFolder}/docs/user-messages-guidelines.md`
4. **Preserve Context**: Ensure the modified message conveys the same meaning and context as the original.
@@ -56,6 +56,8 @@ When modifying user messages, follow these rules:
# After
user_message("Your session has expired. Please log in again.", _version=3)
```
+6. **Replace 'Study' by 'Project'**: If the message contains the word 'Study', replace it with 'Project' to align with our terminology.
+
## Examples
@@ -63,10 +65,10 @@ When modifying user messages, follow these rules:
```python
# Before
-error_dialog(user_message("Failed to save changes."))
+error_dialog(user_message("Failed to save changes in this study."))
# After
-error_dialog(user_message("Unable to save your changes. Please try again.", _version=1))
+error_dialog(user_message("Unable to save your changes in this project.", _version=1))
```
### Example 2: F-string Message Update
diff --git a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py
index 393c0500694..58616a3d335 100644
--- a/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py
+++ b/packages/service-library/src/servicelib/aiohttp/rest_middlewares.py
@@ -36,7 +36,8 @@
DEFAULT_API_VERSION = "v0"
_FMSG_INTERNAL_ERROR_USER_FRIENDLY = user_message(
"We apologize for the inconvenience. "
- "The issue has been recorded, please report it if it persists."
+ "The issue has been recorded, please report it if it persists.",
+ _version=1,
)
diff --git a/services/web/server/src/simcore_service_webserver/catalog/_constants.py b/services/web/server/src/simcore_service_webserver/catalog/_constants.py
index 5fe94022060..ba805923947 100644
--- a/services/web/server/src/simcore_service_webserver/catalog/_constants.py
+++ b/services/web/server/src/simcore_service_webserver/catalog/_constants.py
@@ -1,11 +1,14 @@
from typing import Final
+from common_library.user_messages import user_message
+
from ..constants import MSG_TRY_AGAIN_OR_SUPPORT
-MSG_CATALOG_SERVICE_UNAVAILABLE: Final[str] = (
+MSG_CATALOG_SERVICE_UNAVAILABLE: Final[str] = user_message(
# Most likely the director service is down or misconfigured so the user is asked to try again later.
- "This service is temporarily unavailable. The incident was logged and will be investigated. "
- + MSG_TRY_AGAIN_OR_SUPPORT
+ "The catalog service is currently unavailable. This issue has been logged and will be investigated. "
+ + MSG_TRY_AGAIN_OR_SUPPORT,
+ _version=1,
)
diff --git a/services/web/server/src/simcore_service_webserver/constants.py b/services/web/server/src/simcore_service_webserver/constants.py
index ef963529d53..2962f5a3b0d 100644
--- a/services/web/server/src/simcore_service_webserver/constants.py
+++ b/services/web/server/src/simcore_service_webserver/constants.py
@@ -1,5 +1,6 @@
# pylint:disable=unused-import
+from sys import version
from typing import Final
from common_library.user_messages import user_message
@@ -39,7 +40,7 @@
# main index route name = front-end
INDEX_RESOURCE_NAME: Final[str] = "get_cached_frontend_index"
-MSG_UNDER_DEVELOPMENT: Final[str] = (
+MSG_UNDER_DEVELOPMENT: Final[str] = user_message(
"Under development. Use WEBSERVER_DEV_FEATURES_ENABLED=1 to enable current implementation"
)
@@ -48,7 +49,7 @@
MSG_TRY_AGAIN_OR_SUPPORT: Final[str] = user_message(
- "Please try again shortly. If the issue persists, contact support."
+ "Please try again shortly. If the issue persists, contact support.", _version=1
)
__all__: tuple[str, ...] = (
diff --git a/services/web/server/src/simcore_service_webserver/director_v2/_controller/_rest_exceptions.py b/services/web/server/src/simcore_service_webserver/director_v2/_controller/_rest_exceptions.py
index ac1958870a4..809ec47b6a8 100644
--- a/services/web/server/src/simcore_service_webserver/director_v2/_controller/_rest_exceptions.py
+++ b/services/web/server/src/simcore_service_webserver/director_v2/_controller/_rest_exceptions.py
@@ -87,11 +87,17 @@ async def _handler_director_service_error_as_503_or_4xx(
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
UserDefaultWalletNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Default wallet not found but necessary for computations"),
+ user_message(
+ "A default wallet is required for running computations but could not be found.",
+ _version=1,
+ ),
),
WalletNotEnoughCreditsError: HttpErrorInfo(
status.HTTP_402_PAYMENT_REQUIRED,
- user_message("Wallet does not have enough credits for computations. {reason}"),
+ user_message(
+ "Your wallet does not have sufficient credits to run this computation. {reason}",
+ _version=1,
+ ),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/folders/_common/exceptions_handlers.py b/services/web/server/src/simcore_service_webserver/folders/_common/exceptions_handlers.py
index 875f2790f5d..52f2658ac7c 100644
--- a/services/web/server/src/simcore_service_webserver/folders/_common/exceptions_handlers.py
+++ b/services/web/server/src/simcore_service_webserver/folders/_common/exceptions_handlers.py
@@ -32,49 +32,56 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
FolderNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Folder was not found"),
+ user_message("The requested folder could not be found.", _version=1),
),
WorkspaceNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Workspace was not found"),
+ user_message("The requested workspace could not be found.", _version=1),
),
FolderAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Does not have access to this folder"),
+ user_message("You do not have permission to access this folder.", _version=1),
),
WorkspaceAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Does not have access to this workspace"),
+ user_message(
+ "You do not have permission to access this workspace.", _version=1
+ ),
),
WorkspaceFolderInconsistencyError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("This folder does not exist in this workspace"),
+ user_message(
+ "This folder is not available in the selected workspace.", _version=1
+ ),
),
FolderValueNotPermittedError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- user_message("Provided folder value is not permitted: {reason}"),
+ user_message("The folder operation cannot be completed: {reason}", _version=1),
),
FoldersValueError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- user_message("Invalid folder value set: {reason}"),
+ user_message("The folder configuration is invalid: {reason}", _version=1),
),
ProjectInvalidRightsError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
user_message(
- "Access Denied: You do not have permission to move the project with UUID: {project_uuid}. Tip: Copy and paste the UUID into the search bar to locate the project."
+ "You do not have permission to move the project with UUID: {project_uuid}. To locate this project, copy and paste the UUID into the search bar.",
+ _version=1,
),
),
# Trashing
ProjectRunningConflictError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
user_message(
- "One or more studies in this folder are in use and cannot be trashed. Please stop all services first and try again"
+ "Cannot move folder to trash because it contains projects that are currently running. Please stop all running services first and try again.",
+ _version=2,
),
),
ProjectStoppingError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
user_message(
- "Something went wrong while stopping running services in studies within this folder before trashing. Aborting trash."
+ "Something went wrong while stopping running services in projects within this folder before trashing. Aborting trash.",
+ _version=2,
),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/groups/_common/exceptions_handlers.py b/services/web/server/src/simcore_service_webserver/groups/_common/exceptions_handlers.py
index c6ffa9e7092..c0237b2c45f 100644
--- a/services/web/server/src/simcore_service_webserver/groups/_common/exceptions_handlers.py
+++ b/services/web/server/src/simcore_service_webserver/groups/_common/exceptions_handlers.py
@@ -24,32 +24,40 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
UserNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("User {uid} or {email} not found"),
+ user_message(
+ "The user with ID {uid} or email {email} could not be found.", _version=1
+ ),
),
GroupNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Group {gid} not found"),
+ user_message("The group with ID {gid} could not be found.", _version=1),
),
UserInGroupNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("User not found in group {gid}"),
+ user_message("The user is not a member of group {gid}.", _version=1),
),
UserAlreadyInGroupError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- user_message("User is already in group {gid}"),
+ user_message("The user is already a member of group {gid}.", _version=1),
),
UserInsufficientRightsError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Insufficient rights for {permission} access to group {gid}"),
+ user_message(
+ "You do not have sufficient rights for {permission} access to group {gid}.",
+ _version=1,
+ ),
),
# scicrunch
InvalidRRIDError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- user_message("Invalid RRID {rrid}"),
+ user_message("The RRID {rrid} is not valid.", _version=1),
),
ScicrunchError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- user_message("Cannot get RRID since scicrunch.org service is not reachable."),
+ user_message(
+ "Unable to retrieve RRID information because the scicrunch.org service is currently unavailable.",
+ _version=1,
+ ),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/invitations/errors.py b/services/web/server/src/simcore_service_webserver/invitations/errors.py
index 881b62c6df9..0375c9b6685 100644
--- a/services/web/server/src/simcore_service_webserver/invitations/errors.py
+++ b/services/web/server/src/simcore_service_webserver/invitations/errors.py
@@ -1,16 +1,20 @@
"""
- API plugin errors
+API plugin errors
"""
+from common_library.user_messages import user_message
from ..errors import WebServerBaseError
-MSG_INVALID_INVITATION_URL = "Link seems corrupted or incomplete"
-MSG_INVITATION_ALREADY_USED = "This invitation was already used"
+MSG_INVALID_INVITATION_URL = user_message(
+ "The invitation link appears to be corrupted or incomplete.", _version=1
+)
+MSG_INVITATION_ALREADY_USED = user_message(
+ "This invitation has already been used and cannot be used again.", _version=1
+)
-class InvitationsError(WebServerBaseError, ValueError):
- ...
+class InvitationsError(WebServerBaseError, ValueError): ...
class InvalidInvitationError(InvitationsError):
diff --git a/services/web/server/src/simcore_service_webserver/licenses/_common/exceptions_handlers.py b/services/web/server/src/simcore_service_webserver/licenses/_common/exceptions_handlers.py
index 0fc0c82f5a5..d7358587530 100644
--- a/services/web/server/src/simcore_service_webserver/licenses/_common/exceptions_handlers.py
+++ b/services/web/server/src/simcore_service_webserver/licenses/_common/exceptions_handlers.py
@@ -18,20 +18,30 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
LicensedItemNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Market item {licensed_item_id} not found."),
+ user_message(
+ "The requested market item '{licensed_item_id}' could not be found.",
+ _version=1,
+ ),
),
WalletAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Credit account {wallet_id} forbidden."),
+ user_message(
+ "You do not have permission to access credit account '{wallet_id}'.",
+ _version=1,
+ ),
),
WalletNotEnoughCreditsError: HttpErrorInfo(
status.HTTP_402_PAYMENT_REQUIRED,
- user_message("Not enough credits in the credit account."),
+ user_message(
+ "Your credit account does not have sufficient funds to complete this purchase.",
+ _version=1,
+ ),
),
LicensedItemPricingPlanMatchError: HttpErrorInfo(
status.HTTP_400_BAD_REQUEST,
user_message(
- "The provided pricing plan does not match the one associated with the licensed item."
+ "The selected pricing plan is not valid for this licensed item. Please choose a different plan.",
+ _version=1,
),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/login/_constants.py b/services/web/server/src/simcore_service_webserver/login/_constants.py
index cc10d6ed340..2ee9e5f874f 100644
--- a/services/web/server/src/simcore_service_webserver/login/_constants.py
+++ b/services/web/server/src/simcore_service_webserver/login/_constants.py
@@ -1,79 +1,118 @@
from typing import Final
-MSG_2FA_CODE_SENT: Final[str] = "A code was sent by SMS to {phone_number}."
-MSG_2FA_UNAVAILABLE: Final[str] = "Two-factor authentication is temporarily unavailable"
-MSG_ACTIVATED: Final[str] = "Your account has been activated."
-MSG_ACTIVATION_REQUIRED: Final[str] = (
- "Please activate your account via the email we sent before logging in."
+from common_library.user_messages import user_message
+
+MSG_2FA_CODE_SENT: Final[str] = user_message(
+ "A verification code has been sent via SMS to {phone_number}.", _version=1
+)
+MSG_2FA_UNAVAILABLE: Final[str] = user_message(
+ "Two-factor authentication is temporarily unavailable. Please try again later.",
+ _version=1,
+)
+MSG_ACTIVATED: Final[str] = user_message(
+ "Your account has been successfully activated.", _version=1
+)
+MSG_ACTIVATION_REQUIRED: Final[str] = user_message(
+ "Please activate your account using the activation link we sent to your email before logging in.",
+ _version=1,
+)
+MSG_AUTH_FAILED: Final[str] = user_message(
+ "We couldn't sign you in with those credentials. Please check your email and password and try again.",
+ _version=1,
+)
+MSG_CANT_SEND_MAIL: Final[str] = user_message(
+ "We're unable to send emails at this time. Please try again later.", _version=1
)
-MSG_AUTH_FAILED: Final[str] = (
- "Authorization was not successful. Please check your credentials and try again."
+MSG_CHANGE_EMAIL_REQUESTED: Final[str] = user_message(
+ "Please check your new email address and click the verification link we sent you.",
+ _version=1,
)
-MSG_CANT_SEND_MAIL: Final[str] = (
- "Unable to send email at this time. Please try again later."
+MSG_EMAIL_CHANGED: Final[str] = user_message(
+ "Your email address has been successfully updated.", _version=1
)
-MSG_CHANGE_EMAIL_REQUESTED: Final[str] = (
- "Please click the verification link sent to your new email address."
+MSG_EMAIL_ALREADY_REGISTERED: Final[str] = user_message(
+ "This email address is already associated with an account. Please sign in or use a different email address.",
+ _version=1,
)
-MSG_EMAIL_CHANGED: Final[str] = "Your email address has been updated."
-MSG_EMAIL_ALREADY_REGISTERED: Final[str] = (
- "This email address is already registered. Try logging in or use a different address."
+MSG_EMAIL_SENT: Final[str] = user_message(
+ "We've sent an email to {email} with further instructions.", _version=1
)
-MSG_EMAIL_SENT: Final[str] = "An email was sent to {email} with further instructions."
-MSG_LOGGED_IN: Final[str] = "You have successfully logged in."
-MSG_LOGGED_OUT: Final[str] = "You have successfully logged out."
-MSG_OFTEN_RESET_PASSWORD: Final[str] = (
- "You've requested a password reset recently. Please use the link we sent you or wait before requesting again."
+MSG_LOGGED_IN: Final[str] = user_message("You have successfully signed in.", _version=1)
+MSG_LOGGED_OUT: Final[str] = user_message(
+ "You have successfully signed out.", _version=1
)
-MSG_PASSWORD_CHANGE_NOT_ALLOWED: Final[str] = (
+MSG_OFTEN_RESET_PASSWORD: Final[str] = user_message(
+ "You've recently requested a password reset. Please check your email for the reset link or wait before requesting another one.",
+ _version=1,
+)
+MSG_PASSWORD_CHANGE_NOT_ALLOWED: Final[str] = user_message(
"Unable to reset password. Permissions may have expired or been removed. "
- "Please try again, or contact support if the problem continues: {support_email}"
+ "Please try again, or contact support if the problem continues: {support_email}",
+ _version=1,
+)
+MSG_PASSWORD_CHANGED: Final[str] = user_message(
+ "Your password has been updated.", _version=1
+)
+MSG_PASSWORD_MISMATCH: Final[str] = user_message(
+ "Password and confirmation do not match. Please try again.", _version=1
+)
+MSG_PHONE_MISSING: Final[str] = user_message(
+ "No phone number is associated with this account.", _version=1
+)
+MSG_UNAUTHORIZED_CODE_RESEND_2FA: Final[str] = user_message(
+ "You can no longer resend the verification code. Please restart the verification process.",
+ _version=2,
)
-MSG_PASSWORD_CHANGED: Final[str] = "Your password has been updated."
-MSG_PASSWORD_MISMATCH: Final[str] = (
- "Password and confirmation do not match. Please try again."
+MSG_UNAUTHORIZED_LOGIN_2FA: Final[str] = user_message(
+ "You can no longer submit a verification code. Please restart the login process.",
+ _version=2,
)
-MSG_PHONE_MISSING: Final[str] = "No phone number is associated with this account."
-MSG_UNAUTHORIZED_CODE_RESEND_2FA: Final[str] = (
- "You can no longer resend the code. Please restart the verification process."
+MSG_UNAUTHORIZED_REGISTER_PHONE: Final[str] = user_message(
+ "Phone registration is no longer allowed. Please restart the registration process.",
+ _version=1,
)
-MSG_UNAUTHORIZED_LOGIN_2FA: Final[str] = (
- "You can no longer submit a code. Please restart the login process."
+MSG_UNAUTHORIZED_PHONE_CONFIRMATION: Final[str] = user_message(
+ "You can no longer submit a verification code. Please restart the confirmation process.",
+ _version=2,
)
-MSG_UNAUTHORIZED_REGISTER_PHONE: Final[str] = (
- "Phone registration is no longer allowed. Please restart the registration process."
+MSG_UNKNOWN_EMAIL: Final[str] = user_message(
+ "This email address is not registered.", _version=1
)
-MSG_UNAUTHORIZED_PHONE_CONFIRMATION: Final[str] = (
- "You can no longer submit a code. Please restart the confirmation process."
+MSG_USER_DELETED: Final[str] = user_message(
+ "This account is scheduled for deletion. To reactivate it or for more information, please contact support: {support_email}",
+ _version=1,
)
-MSG_UNKNOWN_EMAIL: Final[str] = "This email address is not registered."
-MSG_USER_DELETED: Final[str] = (
- "This account is scheduled for deletion. To reactivate it or for more information, please contact support: {support_email}"
+MSG_USER_BANNED: Final[str] = user_message(
+ "Access to this account is no longer available. Please contact support for more information: {support_email}",
+ _version=1,
)
-MSG_USER_BANNED: Final[str] = (
- "Access to this account is no longer available. Please contact support for more information: {support_email}"
+MSG_USER_EXPIRED: Final[str] = user_message(
+ "This account has expired and access is no longer available. Please contact support for assistance: {support_email}",
+ _version=1,
)
-MSG_USER_EXPIRED: Final[str] = (
- "This account has expired and access is no longer available. Please contact support for assistance: {support_email}"
+MSG_USER_DISABLED: Final[str] = user_message(
+ "This account has been disabled and cannot be registered again. Please contact support for details: {support_email}",
+ _version=1,
)
-MSG_USER_DISABLED: Final[str] = (
- "This account has been disabled and cannot be registered again. Please contact support for details: {support_email}"
+MSG_WRONG_2FA_CODE__INVALID: Final[str] = user_message(
+ "The verification code entered is not valid. Please enter a valid verification code or generate a new one.",
+ _version=2,
)
-MSG_WRONG_2FA_CODE__INVALID: Final[str] = (
- "The code entered is not valid. Please enter a valid code or generate a new one."
+MSG_WRONG_2FA_CODE__EXPIRED: Final[str] = user_message(
+ "The verification code is either incorrect or has expired. Please request a new verification code and try again.",
+ _version=3,
)
-MSG_WRONG_2FA_CODE__EXPIRED: Final[str] = (
- "The code has expired. Please generate a new code."
+MSG_WRONG_CAPTCHA__INVALID: Final[str] = user_message(
+ "The CAPTCHA entered is incorrect. Please try again.", _version=1
)
-MSG_WRONG_CAPTCHA__INVALID: Final[str] = (
- "The CAPTCHA entered is incorrect. Please try again."
+MSG_WRONG_PASSWORD: Final[str] = user_message(
+ "The password is incorrect. Please try again.", _version=1
)
-MSG_WRONG_PASSWORD: Final[str] = "The password is incorrect. Please try again."
-MSG_WEAK_PASSWORD: Final[str] = (
- "Password must be at least {LOGIN_PASSWORD_MIN_LENGTH} characters long."
+MSG_WEAK_PASSWORD: Final[str] = user_message(
+ "Password must be at least {LOGIN_PASSWORD_MIN_LENGTH} characters long.", _version=1
)
-MSG_INVITATIONS_CONTACT_SUFFIX: Final[str] = (
- "Please contact our support team to request a new invitation."
+MSG_INVITATIONS_CONTACT_SUFFIX: Final[str] = user_message(
+ "Please contact our support team to request a new invitation.", _version=1
)
# Login Accepted Response Codes:
diff --git a/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py b/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py
index 488189a81a5..ef74187c5df 100644
--- a/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py
+++ b/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py
@@ -5,6 +5,7 @@
import arrow
from aiohttp import web
+from common_library.user_messages import user_message
from models_library.api_schemas_webserver.wallets import (
PaymentID,
PaymentMethodID,
@@ -36,7 +37,11 @@
_logger = logging.getLogger(__name__)
-MSG_WALLET_NO_ACCESS_ERROR = "User {user_id} does not have necessary permissions to do a payment into wallet {wallet_id}"
+MSG_WALLET_NO_ACCESS_ERROR = user_message(
+ "You do not have the necessary permissions to make payments to wallet {wallet_id}.",
+ _version=1,
+)
+
_FAKE_PAYMENT_TRANSACTION_ID_PREFIX = "fpt"
diff --git a/services/web/server/src/simcore_service_webserver/products/_controller/rest_exceptions.py b/services/web/server/src/simcore_service_webserver/products/_controller/rest_exceptions.py
index 9402486e27e..78635508bd9 100644
--- a/services/web/server/src/simcore_service_webserver/products/_controller/rest_exceptions.py
+++ b/services/web/server/src/simcore_service_webserver/products/_controller/rest_exceptions.py
@@ -13,13 +13,16 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
ProductNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("{product_name} was not found"),
+ user_message(
+ "This product could not be found." + MSG_TRY_AGAIN_OR_SUPPORT, _version=1
+ ),
),
MissingStripeConfigError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
user_message(
- "{product_name} service is currently unavailable."
- + MSG_TRY_AGAIN_OR_SUPPORT
+ "This service is temporarily unavailable due to a configuration issue. "
+ + MSG_TRY_AGAIN_OR_SUPPORT,
+ _version=1,
),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/projects/_controller/_rest_exceptions.py b/services/web/server/src/simcore_service_webserver/projects/_controller/_rest_exceptions.py
index ee6ffe52408..e703b0ec865 100644
--- a/services/web/server/src/simcore_service_webserver/projects/_controller/_rest_exceptions.py
+++ b/services/web/server/src/simcore_service_webserver/projects/_controller/_rest_exceptions.py
@@ -55,11 +55,11 @@
_FOLDER_ERRORS: ExceptionToHttpErrorMap = {
FolderAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Access to folder forbidden"),
+ user_message("Access to this folder is forbidden.", _version=1),
),
FolderNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Folder not found: {reason}"),
+ user_message("The requested folder could not be found: {reason}", _version=1),
),
}
@@ -67,15 +67,19 @@
_NODE_ERRORS: ExceptionToHttpErrorMap = {
NodeNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Node '{node_uuid}' not found in project '{project_uuid}'"),
+ user_message(
+ "Node '{node_uuid}' was not found in project '{project_uuid}'.", _version=1
+ ),
),
ParentNodeNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Parent node '{node_uuid}' not found"),
+ user_message("Parent node '{node_uuid}' was not found.", _version=1),
),
ProjectNodeRequiredInputsNotSetError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- user_message("Project node is required but input is not set"),
+ user_message(
+ "Required input values for this project node have not been set.", _version=1
+ ),
),
}
@@ -83,59 +87,91 @@
_PROJECT_ERRORS: ExceptionToHttpErrorMap = {
ProjectDeleteError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- "Failed to complete deletion of '{project_uuid}': {reason}",
+ user_message(
+ "Unable to complete deletion of project '{project_uuid}': {reason}",
+ _version=1,
+ ),
),
ProjectGroupNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Project group not found: {reason}",
+ user_message(
+ "The requested project group could not be found: {reason}", _version=1
+ ),
),
ProjectInvalidRightsError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- "Do not have sufficient access rights on project {project_uuid} for this action",
+ user_message(
+ "You do not have sufficient access rights to perform this action on project {project_uuid}.",
+ _version=1,
+ ),
),
InsufficientRoleForProjectTemplateTypeUpdateError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- "Do not have sufficient access rights on updating project template type",
+ user_message(
+ "You do not have sufficient permissions to update the project template type.",
+ _version=1,
+ ),
),
ProjectInvalidUsageError: HttpErrorInfo(
status.HTTP_422_UNPROCESSABLE_ENTITY,
- "Invalid usage for project",
+ user_message("The project cannot be used in this way.", _version=1),
),
ProjectNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Project {project_uuid} not found",
+ user_message("Project {project_uuid} could not be found.", _version=1),
),
ProjectOwnerNotFoundInTheProjectAccessRightsError: HttpErrorInfo(
status.HTTP_400_BAD_REQUEST,
- "Project owner identifier was not found in the project's access-rights field",
+ user_message(
+ "The project owner could not be found in the project's access rights.",
+ _version=1,
+ ),
),
ProjectTooManyProjectOpenedError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- "You cannot open more than {max_num_projects} study/ies at once. Please close another study and retry.",
+ user_message(
+ "You cannot open more than {max_num_projects} project/s at once. Please close another project and retry.",
+ _version=2,
+ ),
),
ProjectStartsTooManyDynamicNodesError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- "The maximal amount of concurrently running dynamic services was reached. Please manually stop a service and retry.",
+ user_message(
+ "The maximum number of concurrently running dynamic services has been reached. Please manually stop a service and retry.",
+ _version=1,
+ ),
),
ProjectWalletPendingTransactionError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
- "Project has currently pending transactions. It is forbidden to change wallet.",
+ user_message(
+ "This project has pending transactions. Changing the wallet is currently not allowed.",
+ _version=1,
+ ),
),
ProjectInDebtCanNotChangeWalletError: HttpErrorInfo(
status.HTTP_402_PAYMENT_REQUIRED,
- "Unable to change the credit account linked to the project. The project is embargoed because the last transaction of {debt_amount} resulted in the credit account going negative.",
+ user_message(
+ "Unable to change the credit account linked to the project. The project is embargoed because the last transaction of {debt_amount} resulted in the credit account going negative.",
+ _version=1,
+ ),
),
ProjectInDebtCanNotOpenError: HttpErrorInfo(
status.HTTP_402_PAYMENT_REQUIRED,
- "Unable to open the project. The project is embargoed because the last transaction of {debt_amount} resulted in the credit account going negative.",
+ user_message(
+ "Unable to open the project. The project is embargoed because the last transaction of {debt_amount} resulted in the credit account going negative.",
+ _version=1,
+ ),
),
WrongTagIdsInQueryError: HttpErrorInfo(
status.HTTP_400_BAD_REQUEST,
- "Wrong tag IDs in query",
+ user_message("Invalid tag IDs were provided in the request.", _version=1),
),
ProjectTypeAndTemplateIncompatibilityError: HttpErrorInfo(
status.HTTP_400_BAD_REQUEST,
- "Wrong project type and template type combination: {reason}",
+ user_message(
+ "The project type and template type combination is not valid: {reason}",
+ _version=1,
+ ),
),
}
@@ -143,11 +179,13 @@
_WORKSPACE_ERRORS: ExceptionToHttpErrorMap = {
WorkspaceAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- "Access to workspace forbidden: {reason}",
+ user_message("Access to this workspace is forbidden: {reason}", _version=1),
),
WorkspaceNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Workspace not found: {reason}",
+ user_message(
+ "The requested workspace could not be found: {reason}", _version=1
+ ),
),
}
@@ -155,15 +193,21 @@
_WALLET_ERRORS: ExceptionToHttpErrorMap = {
UserDefaultWalletNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Wallet not found: {reason}",
+ user_message("The requested wallet could not be found: {reason}", _version=1),
),
WalletAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- "Payment required, but the user lacks access to the project's linked wallet: Wallet access forbidden. {reason}",
+ user_message(
+ "Payment is required, but you do not have access to the project's linked wallet: {reason}",
+ _version=1,
+ ),
),
WalletNotEnoughCreditsError: HttpErrorInfo(
status.HTTP_402_PAYMENT_REQUIRED,
- "Wallet does not have enough credits. {reason}",
+ user_message(
+ "The wallet does not have enough credits to complete this operation: {reason}",
+ _version=1,
+ ),
),
}
@@ -171,11 +215,11 @@
_PRICING_ERRORS: ExceptionToHttpErrorMap = {
DefaultPricingPlanNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Default pricing plan not found",
+ user_message("The default pricing plan could not be found.", _version=1),
),
DefaultPricingUnitNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Default pricing unit not found",
+ user_message("The default pricing unit could not be found.", _version=1),
),
}
@@ -183,11 +227,13 @@
_CONVERSATION_ERRORS: ExceptionToHttpErrorMap = {
ConversationErrorNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Conversation not found",
+ user_message("The requested conversation could not be found.", _version=1),
),
ConversationMessageErrorNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- "Conversation message not found",
+ user_message(
+ "The requested conversation message could not be found.", _version=1
+ ),
),
}
@@ -195,18 +241,24 @@
_OTHER_ERRORS: ExceptionToHttpErrorMap = {
CatalogNotAvailableError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
- "This service is currently not available",
+ user_message("The catalog service is currently unavailable.", _version=1),
),
ClustersKeeperNotAvailableError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
- "Clusters-keeper service is not available",
+ user_message(
+ "The clusters-keeper service is currently unavailable.", _version=1
+ ),
),
CatalogForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- "Catalog forbidden: Insufficient access rights for {name}",
+ user_message(
+ "Access denied: You do not have sufficient permissions for {name}.",
+ _version=1,
+ ),
),
CatalogItemNotFoundError: HttpErrorInfo(
- status.HTTP_404_NOT_FOUND, "{name} was not found"
+ status.HTTP_404_NOT_FOUND,
+ user_message("The requested item '{name}' was not found.", _version=1),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/resource_usage/_constants.py b/services/web/server/src/simcore_service_webserver/resource_usage/_constants.py
index 64586ad4c49..5b4741478d6 100644
--- a/services/web/server/src/simcore_service_webserver/resource_usage/_constants.py
+++ b/services/web/server/src/simcore_service_webserver/resource_usage/_constants.py
@@ -1,9 +1,14 @@
from typing import Final
+from common_library.user_messages import user_message
+
APP_RABBITMQ_CONSUMERS_KEY: Final[str] = f"{__name__}.rabbit_consumers"
-MSG_RESOURCE_USAGE_TRACKER_SERVICE_UNAVAILABLE: Final[
- str
-] = "Currently resource usage tracker service is unavailable, please try again later"
+MSG_RESOURCE_USAGE_TRACKER_SERVICE_UNAVAILABLE: Final[str] = user_message(
+ "The resource usage tracking service is temporarily unavailable. Please try again in a few moments.",
+ _version=1,
+)
-MSG_RESOURCE_USAGE_TRACKER_NOT_FOUND: Final[str] = "Not Found"
+MSG_RESOURCE_USAGE_TRACKER_NOT_FOUND: Final[str] = user_message(
+ "The requested resource usage information could not be found.", _version=1
+)
diff --git a/services/web/server/src/simcore_service_webserver/security/_constants.py b/services/web/server/src/simcore_service_webserver/security/_constants.py
index 62974bb6adb..b10848ee522 100644
--- a/services/web/server/src/simcore_service_webserver/security/_constants.py
+++ b/services/web/server/src/simcore_service_webserver/security/_constants.py
@@ -1,5 +1,10 @@
from typing import Final
-MSG_AUTH_NOT_AVAILABLE: Final[str] = "Authentication service is temporary unavailable"
-MSG_UNAUTHORIZED: Final[str] = "Unauthorized"
+from common_library.user_messages import user_message
+
+MSG_UNAUTHORIZED: Final[str] = user_message("Unauthorized")
+MSG_AUTH_NOT_AVAILABLE: Final[str] = user_message(
+ "Authentication service is temporary unavailable"
+)
+
PERMISSION_PRODUCT_LOGIN_KEY: Final[str] = "product.login"
diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_constants.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_constants.py
index b36820434b0..3a2409cf4e9 100644
--- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_constants.py
+++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_constants.py
@@ -1,34 +1,44 @@
from typing import Final
+from common_library.user_messages import user_message
+
#
# NOTE: MSG_$(ERROR_CODE_NAME) strings MUST be human readable messages
# Please keep alphabetical order
#
-MSG_PROJECT_NOT_FOUND: Final[str] = "Cannot find any study with ID '{project_id}'"
+MSG_PROJECT_NOT_FOUND: Final[str] = user_message(
+ "The project with ID '{project_id}' could not be found.", _version=1
+)
-# 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 project ID does not exists OR is not shared with everyone
+MSG_PROJECT_NOT_PUBLISHED: Final[str] = user_message(
+ "The project with ID '{project_id}' is not available or not shared.", _version=1
+)
-# 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] = (
- "Only available for registered users.
"
- "Please login and try again.
"
- "If you don't have an account, please request one at {support_email}
"
+# This error happens when the linked project ID does not exists OR is not shared with everyone OR is NOT public
+MSG_PUBLIC_PROJECT_NOT_PUBLISHED: Final[str] = user_message(
+ "This project is only available for registered users.
"
+ "Please log in and try again.
"
+ "If you don't have an account, please request one at {support_email}.
",
+ _version=1,
)
-MSG_GUESTS_NOT_ALLOWED: Final[str] = (
- "Access restricted to registered users.
"
- "If you don't have an account, please email to support and request one
"
+MSG_GUESTS_NOT_ALLOWED: Final[str] = user_message(
+ "Access is restricted to registered users.
"
+ "If you don't have an account, please contact support to request one.
",
+ _version=1,
)
-MSG_TOO_MANY_GUESTS: Final[str] = (
- "We have reached the maximum of anonymous users allowed the platform. "
- "Please try later or login with a registered account."
+MSG_TOO_MANY_GUESTS: Final[str] = user_message(
+ "We have reached the maximum number of anonymous users allowed on the platform. "
+ "Please try again later or log in with a registered account.",
+ _version=1,
)
-MSG_UNEXPECTED_DISPATCH_ERROR: Final[str] = (
- "Sorry, but looks like something unexpected went wrong!"
- "We track these errors automatically, but if the problem persists feel free to contact us."
- "In the meantime, try refreshing."
+MSG_UNEXPECTED_DISPATCH_ERROR: Final[str] = user_message(
+ "Sorry, something unexpected went wrong! "
+ "We track these errors automatically, but if the problem persists please contact us. "
+ "In the meantime, try refreshing the page.",
+ _version=1,
)
diff --git a/services/web/server/src/simcore_service_webserver/tags/_rest.py b/services/web/server/src/simcore_service_webserver/tags/_rest.py
index 10d4c86a422..21dc5e97c6e 100644
--- a/services/web/server/src/simcore_service_webserver/tags/_rest.py
+++ b/services/web/server/src/simcore_service_webserver/tags/_rest.py
@@ -39,27 +39,35 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
TagNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Tag {tag_id} not found: either no access or does not exists"),
+ user_message(
+ "The tag '{tag_id}' could not be found or you don't have access to it.",
+ _version=1,
+ ),
),
TagOperationNotAllowedError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
user_message(
- "Could not {operation} tag {tag_id}. Not found or insuficient access."
+ "Unable to {operation} tag '{tag_id}'. The tag was not found or you don't have sufficient access.",
+ _version=1,
),
),
ShareTagWithEveryoneNotAllowedError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Sharing with everyone is not permitted."),
+ user_message("Sharing with everyone is not allowed.", _version=1),
),
ShareTagWithProductGroupNotAllowedError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
user_message(
- "Sharing with all users is only permitted to admin users (e.g. testers, POs, ...)."
+ "Sharing with all users is only allowed for admin users (e.g. testers, POs, ...).",
+ _version=1,
),
),
InsufficientTagShareAccessError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Insufficient access rightst to share (or unshare) tag {tag_id}."),
+ user_message(
+ "You don't have sufficient access rights to share (or unshare) tag '{tag_id}'.",
+ _version=1,
+ ),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/trash/_rest.py b/services/web/server/src/simcore_service_webserver/trash/_rest.py
index 728aca09b64..3fc2cf234d5 100644
--- a/services/web/server/src/simcore_service_webserver/trash/_rest.py
+++ b/services/web/server/src/simcore_service_webserver/trash/_rest.py
@@ -27,13 +27,15 @@
ProjectRunningConflictError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
user_message(
- "Current study is in use and cannot be trashed [project_id={project_uuid}]. Please stop all services first and try again"
+ "The project is currently in use and cannot be moved to trash. Please stop all running services first and try again.",
+ _version=1,
),
),
ProjectStoppingError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
user_message(
- "Something went wrong while stopping services before trashing. Aborting trash."
+ "An error occurred while stopping services before moving to trash. The operation has been cancelled.",
+ _version=1,
),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/users/_users_rest.py b/services/web/server/src/simcore_service_webserver/users/_users_rest.py
index 7590c7fb17f..abb8ff7365d 100644
--- a/services/web/server/src/simcore_service_webserver/users/_users_rest.py
+++ b/services/web/server/src/simcore_service_webserver/users/_users_rest.py
@@ -55,32 +55,40 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
PendingPreRegistrationNotFoundError: HttpErrorInfo(
status.HTTP_400_BAD_REQUEST,
- user_message(PendingPreRegistrationNotFoundError.msg_template),
+ user_message(
+ "No pending registration request found for email {email} in {product_name}.",
+ _version=2,
+ ),
),
UserNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
user_message(
- "This user cannot be found. Either it is not registered or has enabled privacy settings."
+ "The requested user could not be found. "
+ "This may be because the user is not registered or has privacy settings enabled.",
+ _version=1,
),
),
UserNameDuplicateError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
user_message(
- "Username '{user_name}' is already taken. "
- "Consider '{alternative_user_name}' instead."
+ "The username '{user_name}' is already in use. "
+ "Please try '{alternative_user_name}' instead.",
+ _version=1,
),
),
AlreadyPreRegisteredError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
user_message(
- "Found {num_found} matches for '{email}'. Cannot pre-register existing user"
+ "Found {num_found} existing account(s) for '{email}'. Unable to pre-register an existing user.",
+ _version=1,
),
),
MissingGroupExtraPropertiesForProductError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
user_message(
- "The product is not ready for use until the configuration is fully completed. "
- "Please wait and try again. "
+ "This product is currently being configured and is not yet ready for use. "
+ "Please try again later.",
+ _version=1,
),
),
}
diff --git a/services/web/server/src/simcore_service_webserver/utils_rate_limiting.py b/services/web/server/src/simcore_service_webserver/utils_rate_limiting.py
index 2266170c5ac..5311231a29b 100644
--- a/services/web/server/src/simcore_service_webserver/utils_rate_limiting.py
+++ b/services/web/server/src/simcore_service_webserver/utils_rate_limiting.py
@@ -6,6 +6,7 @@
from typing import Final, NamedTuple
from aiohttp.web_exceptions import HTTPTooManyRequests
+from common_library.user_messages import user_message
from models_library.rest_error import EnvelopedError, ErrorGet
from servicelib.aiohttp import status
@@ -15,7 +16,7 @@ class RateLimitSetup(NamedTuple):
interval_seconds: float
-MSG_TOO_MANY_REQUESTS: Final[str] = (
+MSG_TOO_MANY_REQUESTS: Final[str] = user_message(
"Requests are being made too frequently. Please wait a moment before trying again."
)
diff --git a/services/web/server/src/simcore_service_webserver/wallets/_constants.py b/services/web/server/src/simcore_service_webserver/wallets/_constants.py
index 579c403ef28..3cf69f28779 100644
--- a/services/web/server/src/simcore_service_webserver/wallets/_constants.py
+++ b/services/web/server/src/simcore_service_webserver/wallets/_constants.py
@@ -3,10 +3,12 @@
from common_library.user_messages import user_message
MSG_PRICE_NOT_DEFINED_ERROR: Final[str] = user_message(
- "No payments are accepted until this product has a price"
+ "Payments are not currently available for this product as pricing has not been configured.",
+ _version=1,
)
MSG_BILLING_DETAILS_NOT_DEFINED_ERROR: Final[str] = user_message(
- "Payments cannot be processed: Required billing details (e.g. country for tax) are missing from your account."
- "Please contact support to resolve this configuration issue."
+ "Unable to process payment because required billing information (such as country for tax purposes) is missing from your account. "
+ "Please contact support to complete your billing setup.",
+ _version=1,
)
diff --git a/services/web/server/src/simcore_service_webserver/workspaces/_common/exceptions_handlers.py b/services/web/server/src/simcore_service_webserver/workspaces/_common/exceptions_handlers.py
index 4a4b77a5cca..aa11ad4afe4 100644
--- a/services/web/server/src/simcore_service_webserver/workspaces/_common/exceptions_handlers.py
+++ b/services/web/server/src/simcore_service_webserver/workspaces/_common/exceptions_handlers.py
@@ -22,27 +22,36 @@
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
WorkspaceGroupNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Workspace {workspace_id} group {group_id} not found."),
+ user_message(
+ "The requested workspace {workspace_id} group {group_id} could not be found.",
+ _version=1,
+ ),
),
WorkspaceAccessForbiddenError: HttpErrorInfo(
status.HTTP_403_FORBIDDEN,
- user_message("Does not have access to this workspace"),
+ user_message(
+ "You do not have permission to access this workspace.", _version=1
+ ),
),
WorkspaceNotFoundError: HttpErrorInfo(
status.HTTP_404_NOT_FOUND,
- user_message("Workspace not found. {reason}"),
+ user_message(
+ "The requested workspace could not be found. {reason}", _version=1
+ ),
),
# Trashing
ProjectRunningConflictError: HttpErrorInfo(
status.HTTP_409_CONFLICT,
user_message(
- "One or more studies in this workspace are in use and cannot be trashed. Please stop all services first and try again"
+ "Unable to delete workspace because one or more projects are currently running. Please stop all running services and try again.",
+ _version=1,
),
),
ProjectStoppingError: HttpErrorInfo(
status.HTTP_503_SERVICE_UNAVAILABLE,
user_message(
- "Something went wrong while stopping running services in studies within this workspace before trashing. Aborting trash."
+ "Something went wrong while stopping running services in projects within this workspace before trashing. Aborting trash.",
+ _version=1,
),
),
}
diff --git a/services/web/server/tests/unit/with_dbs/03/login/test_login_twofa.py b/services/web/server/tests/unit/with_dbs/03/login/test_login_twofa.py
index 3bd849f086b..c84bc7ab5ac 100644
--- a/services/web/server/tests/unit/with_dbs/03/login/test_login_twofa.py
+++ b/services/web/server/tests/unit/with_dbs/03/login/test_login_twofa.py
@@ -24,6 +24,7 @@
from simcore_service_webserver.login._constants import (
CODE_2FA_SMS_CODE_REQUIRED,
MSG_2FA_UNAVAILABLE,
+ MSG_LOGGED_IN,
)
from simcore_service_webserver.login._login_repository_legacy import AsyncpgStorage
from simcore_service_webserver.login._twofa_service import (
@@ -307,7 +308,7 @@ def _get_confirmation_link_from_email():
},
)
data, _ = await assert_status(response, status.HTTP_200_OK)
- assert "logged in" in data["message"]
+ assert MSG_LOGGED_IN in data["message"]
async def test_can_register_same_phone_in_different_accounts(