chore: added approved messages (#40108)

## Description
Conversation link -
https://theappsmith.slack.com/archives/C0341RERY4R/p1743064966404339

EE PR - https://github.com/appsmithorg/appsmith-ee/pull/6989


Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/14355493550>
> Commit: a3fdc2ea4ad72061f843586fd17706b3ec3ddd49
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=14355493550&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 09 Apr 2025 12:22:30 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
- Enhanced error messaging across authentication flows (login, signup,
verification) to ensure safe and clear feedback.
- Expanded user feedback for authentication issues, including login
failures, account lockouts, and session-related errors.
- Introduced a structured set of approved static and dynamic error
messages.

- **Style**
- Standardized punctuation and formatting in user messages for improved
readability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Apeksha Bhosale 2025-04-10 10:54:18 +05:30 committed by GitHub
parent 0c9d96c149
commit 82f061a1be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 170 additions and 3 deletions

View File

@ -0,0 +1,137 @@
import {
createMessage,
DEFAULT_ERROR_MESSAGE,
ERROR_401,
FORM_VALIDATION_EMPTY_PASSWORD,
FORM_VALIDATION_INVALID_EMAIL,
VERIFY_ERROR_ALREADY_VERIFIED_TITLE,
VERIFY_ERROR_EXPIRED_TITLE,
VERIFY_ERROR_MISMATCH_TITLE,
FORM_VALIDATION_EMPTY_EMAIL,
AUTH_LOGIN_TOO_MANY_ATTEMPTS,
AUTH_INVALID_CREDENTIALS,
AUTH_UNAUTHORIZED,
AUTH_NOT_LOGGED_IN,
AUTH_RESET_PASSWORD_REQUEST_INVALID,
AUTH_LOGIN_METHOD_NOT_SUPPORTED,
AUTH_ACCOUNT_LOCKED,
AUTH_SESSION_INVALID,
EMAIL_VERIFICATION_NOT_ENABLED,
GOOGLE_RECAPTCHA_FAILED,
PASSWORD_INSUFFICIENT_STRENGTH,
LOGIN_PAGE_INVALID_CREDS_ERROR,
FORM_VALIDATION_PASSWORD_RULE,
FORM_VALIDATION_INVALID_PASSWORD,
RESET_PASSWORD_EXPIRED_TOKEN,
RESET_PASSWORD_INVALID_TOKEN,
FORGOT_PASSWORD_PAGE_SUBTITLE,
SIGNUP_PAGE_SUCCESS,
RESET_PASSWORD_RESET_SUCCESS,
CREATE_PASSWORD_RESET_SUCCESS,
WELCOME_FORM_PASSWORDS_NOT_MATCHING_ERROR_MESSAGE,
WELCOME_FORM_STRONG_PASSWORD_ERROR_MESSAGE,
} from "./messages";
// List of approved static error messages that can be shown to users
export const APPROVED_ERROR_MESSAGES = {
// Static messages that are exact matches
static: [
// Authentication & Authorization
ERROR_401,
AUTH_LOGIN_TOO_MANY_ATTEMPTS,
AUTH_INVALID_CREDENTIALS,
AUTH_UNAUTHORIZED,
AUTH_NOT_LOGGED_IN,
AUTH_RESET_PASSWORD_REQUEST_INVALID,
AUTH_LOGIN_METHOD_NOT_SUPPORTED,
AUTH_ACCOUNT_LOCKED,
AUTH_SESSION_INVALID,
LOGIN_PAGE_INVALID_CREDS_ERROR,
FORM_VALIDATION_PASSWORD_RULE,
FORM_VALIDATION_INVALID_PASSWORD,
FORM_VALIDATION_EMPTY_PASSWORD,
FORM_VALIDATION_EMPTY_EMAIL,
FORM_VALIDATION_INVALID_EMAIL,
RESET_PASSWORD_EXPIRED_TOKEN,
RESET_PASSWORD_INVALID_TOKEN,
FORGOT_PASSWORD_PAGE_SUBTITLE,
SIGNUP_PAGE_SUCCESS,
RESET_PASSWORD_RESET_SUCCESS,
CREATE_PASSWORD_RESET_SUCCESS,
WELCOME_FORM_PASSWORDS_NOT_MATCHING_ERROR_MESSAGE,
WELCOME_FORM_STRONG_PASSWORD_ERROR_MESSAGE,
// Signup Specific
VERIFY_ERROR_ALREADY_VERIFIED_TITLE,
VERIFY_ERROR_EXPIRED_TITLE,
EMAIL_VERIFICATION_NOT_ENABLED,
VERIFY_ERROR_MISMATCH_TITLE,
GOOGLE_RECAPTCHA_FAILED,
PASSWORD_INSUFFICIENT_STRENGTH,
],
// Patterns for dynamic messages that are allowed
patterns: [
// Authentication patterns
/^Please use [a-zA-Z0-9\s\.-]+ authentication to login to Appsmith$/,
/^Authentication failed with error: [a-zA-Z0-9\s.,_\-:()'"]+$/,
/^Invalid email domain [a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]\.[a-zA-Z]{2,} used for sign in\/sign up\. Please contact the administrator to configure this domain if this is unexpected\.$/,
/^Password length should be between [0-9]+ and [0-9]+$/,
/^Unable to find user with email [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
/^Please enter a valid parameter [a-zA-Z][a-zA-Z0-9._-]*\.$/,
/^There is already an account registered with this email [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\. Please sign in instead\.$/,
/^Cannot find an outstanding reset password request for this email\. Please initiate a request via "forgot password" button to reset your password$/,
/^A password reset link has been sent to your email address [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} registered with Appsmith\.$/,
/^Password must be [0-9]+-[0-9]+ characters long and include at least one uppercase letter, one lowercase letter, one number, one symbol, and no whitespaces\.$/,
/^Signup is restricted on this instance of Appsmith\. Please contact the administrator to get an invite for user [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\.$/,
/^The user [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} has already been added to the workspace with role [a-zA-Z0-9\s_-]+\. To change the role, please navigate to `Manage users` page\.$/,
],
};
/**
* Checks if an error message is in the approved list
* @param message The error message to validate
* @returns boolean indicating if message is approved
*/
export function isApprovedErrorMessage(message: string): boolean {
// First check static messages
if (
APPROVED_ERROR_MESSAGES.static.some((msg) =>
typeof msg === "function" ? msg() === message : msg === message,
)
) {
return true;
}
// Then check regex patterns
return APPROVED_ERROR_MESSAGES.patterns.some((pattern) =>
pattern.test(message),
);
}
/**
* Returns either the approved message or a default error message
* @param message The error message to validate
* @returns The original message if approved, or a default message
*/
export function getSafeErrorMessage(message: string): string {
const isApproved = isApprovedErrorMessage(message);
if (!isApproved) {
return createMessage(DEFAULT_ERROR_MESSAGE);
}
// If it's a static message, find and return it wrapped in createMessage
const staticMessage = APPROVED_ERROR_MESSAGES.static.find((msg) =>
typeof msg === "function" ? msg() === message : msg === message,
);
if (staticMessage) {
return typeof staticMessage === "function"
? createMessage(staticMessage)
: staticMessage;
}
// For pattern matches, return the original message wrapped in createMessage
return createMessage(() => message);
}

View File

@ -2663,3 +2663,27 @@ export const ADD_CUSTOM_ACTION = () => "Add custom action";
export const CONFIG_PROPERTY_COMMAND = () => "command";
export const CUSTOM_ACTION_LABEL = () => "Custom Action";
export const AUTH_LOGIN_TOO_MANY_ATTEMPTS = () =>
"Too many login attempts. Please try again after some time.";
export const AUTH_INVALID_CREDENTIALS = () =>
"Invalid credentials provided. Did you input the credentials correctly?";
export const AUTH_UNAUTHORIZED = () => "Unauthorized access";
export const AUTH_NOT_LOGGED_IN = () =>
"You are not logged in. Please sign in with the registered email ID or sign up";
export const AUTH_RESET_PASSWORD_REQUEST_INVALID = () =>
'Cannot find an outstanding reset password request for this email. Please initiate a request via "forgot password" button to reset your password';
export const AUTH_LOGIN_METHOD_NOT_SUPPORTED = () =>
"Login with this method is not supported.";
export const AUTH_ACCOUNT_LOCKED = () =>
"Account temporarily locked due to multiple failed attempts. Please try again later.";
export const AUTH_SESSION_INVALID = () =>
"User session is invalid. Please log out and log in again.";
// Signup & Email verification
export const EMAIL_VERIFICATION_NOT_ENABLED = () =>
"Email Verification not enabled";
export const GOOGLE_RECAPTCHA_FAILED = () =>
"Google reCAPTCHA verification failed";
export const PASSWORD_INSUFFICIENT_STRENGTH = () =>
"Insufficient password strength";

View File

@ -0,0 +1 @@
export * from "ce/constants/approvedErrorMessages";

View File

@ -53,6 +53,7 @@ import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import { getHTMLPageTitle } from "ee/utils/BusinessFeatures/brandingPageHelpers";
import * as Sentry from "@sentry/react";
import CsrfTokenInput from "pages/UserAuth/CsrfTokenInput";
import { getSafeErrorMessage } from "ee/constants/approvedErrorMessages";
const validate = (values: LoginFormValues, props: ValidateProps) => {
const errors: LoginFormValues = {};
@ -175,7 +176,7 @@ export function Login(props: LoginFormProps) {
}
>
{!!errorMessage && errorMessage !== "true"
? errorMessage
? getSafeErrorMessage(errorMessage)
: createMessage(LOGIN_PAGE_INVALID_CREDS_ERROR)}
</Callout>
)}

View File

@ -65,6 +65,7 @@ import CsrfTokenInput from "pages/UserAuth/CsrfTokenInput";
import { useIsCloudBillingEnabled } from "hooks";
import { isLoginHostname } from "utils/cloudBillingUtils";
import { getIsAiAgentFlowEnabled } from "ee/selectors/aiAgentSelectors";
import { getSafeErrorMessage } from "ee/constants/approvedErrorMessages";
declare global {
interface Window {
@ -260,7 +261,9 @@ export function SignUp(props: SignUpFormProps) {
<title>{htmlPageTitle}</title>
</Helmet>
{showError && <Callout kind="error">{errorMessage}</Callout>}
{showError && (
<Callout kind="error">{getSafeErrorMessage(errorMessage)}</Callout>
)}
{socialLoginList.length > 0 && (
<ThirdPartyAuth logins={socialLoginList} type={"SIGNUP"} />
)}

View File

@ -14,6 +14,7 @@ import { useResendEmailVerification } from "./helpers";
import type { RouteComponentProps } from "react-router-dom";
import styled from "styled-components";
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
import { getSafeErrorMessage } from "ee/constants/approvedErrorMessages";
const Body = styled.div`
display: flex;
@ -77,7 +78,7 @@ const VerificationError = (
<Container testId="verification-error" title="">
<Body>
<Callout kind="error">
<Text kind={"body-m"}>{message}</Text>
<Text kind={"body-m"}>{getSafeErrorMessage(message || "")}</Text>
</Callout>
</Body>
<Body>