## Problem With the introduction of cloud billing and multi-organization support, users can now access Appsmith through organization-specific subdomains (e.g., `testorg.appsmith.com`). However, when users attempt to access non-existent domains (e.g., `domaindoesnotexist.appsmith.com`), the system fails to return a user object, causing the application to get stuck in an infinite loading state. ## 🔍 Root Cause The issue was in the `LandingScreen` component's conditional logic: ```tsx // Previous implementation ❌ if (props.user && window.location.pathname === BASE_URL) { if (props.user.email === ANONYMOUS_USERNAME) { return <Redirect to={AUTH_LOGIN_URL} />; } else { return <Redirect to={APPLICATIONS_URL} />; } } ``` **The problem:** When accessing a non-existent domain, `props.user` is `null`/`undefined`, causing the condition `props.user && window.location.pathname === BASE_URL` to evaluate to `false`. This prevented the redirect logic from executing, leaving users on a perpetual loading screen instead of being properly redirected to the login page. ## ✅ Solution Updated the conditional logic to handle cases where the user object is undefined: ```tsx // Fixed implementation ✅ if (window.location.pathname === BASE_URL) { if (!props.user || props.user.email === ANONYMOUS_USERNAME) { return <Redirect to={AUTH_LOGIN_URL} />; } else { return <Redirect to={APPLICATIONS_URL} />; } } ``` ### Key changes: 1. **Removed the `props.user &&` guard condition** - Now the redirect logic always executes when on the base URL 2. **Added explicit null/undefined check** - The condition `!props.user || props.user.email === ANONYMOUS_USERNAME` properly handles both scenarios: - When no user object exists (non-existent domains) - When the user is anonymous ## 📊 Impact | Scenario | Before | After | |----------|---------|-------| | Valid org domain + authenticated user | ✅ Redirects to applications | ✅ Redirects to applications | | Valid org domain + anonymous user | ✅ Redirects to login | ✅ Redirects to login | | **Non-existent org domain** | ❌ **Infinite loading screen** | ✅ **Redirects to login** | | Direct access to login URL | ✅ Works as expected | ✅ Works as expected | ## 🧪 Testing Scenarios This fix addresses the following scenarios in the cloud billing multi-org environment: - [x] Valid organization domain with authenticated user → Redirects to applications - [x] Valid organization domain with anonymous user → Redirects to login - [x] **Non-existent organization domain → Redirects to login (instead of infinite loading)** - [x] Direct access to login URL → Works as expected ## Automation /ok-to-test tags="@tag.Authentication, @tag.Sanity" ### 🔍 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/15438685266> > Commit: afee6b1b89b3bf2c65290a1cef9355e72c1ab14e > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15438685266&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Authentication, @tag.Sanity` > Spec: > <hr>Wed, 04 Jun 2025 10:09:08 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 - **Bug Fixes** - Improved user redirection on the landing screen to ensure users are correctly routed based on their authentication status. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
39 lines
1.2 KiB
TypeScript
Executable File
39 lines
1.2 KiB
TypeScript
Executable File
import React from "react";
|
|
import type { DefaultRootState } from "react-redux";
|
|
import { getCurrentUser, getUserAuthError } from "selectors/usersSelectors";
|
|
import { connect } from "react-redux";
|
|
import type { User } from "constants/userConstants";
|
|
import { ANONYMOUS_USERNAME } from "constants/userConstants";
|
|
import { Redirect } from "react-router";
|
|
import { APPLICATIONS_URL, AUTH_LOGIN_URL, BASE_URL } from "constants/routes";
|
|
import PageLoadingBar from "pages/common/PageLoadingBar";
|
|
import ServerUnavailable from "pages/common/ErrorPages/ServerUnavailable";
|
|
|
|
interface Props {
|
|
user?: User;
|
|
authError: string;
|
|
}
|
|
|
|
function LandingScreen(props: Props) {
|
|
if (window.location.pathname === BASE_URL) {
|
|
if (!props.user || props.user.email === ANONYMOUS_USERNAME) {
|
|
return <Redirect to={AUTH_LOGIN_URL} />;
|
|
} else {
|
|
return <Redirect to={APPLICATIONS_URL} />;
|
|
}
|
|
}
|
|
|
|
if (props.authError && props.authError.length) {
|
|
return <ServerUnavailable />;
|
|
}
|
|
|
|
return <PageLoadingBar />;
|
|
}
|
|
|
|
const mapStateToProps = (state: DefaultRootState) => ({
|
|
user: getCurrentUser(state),
|
|
authError: getUserAuthError(state),
|
|
});
|
|
|
|
export default connect(mapStateToProps)(LandingScreen);
|