Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/dashboard/app-ciab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@automattic/api-queries';
/* eslint-enable no-restricted-imports */
import boot from '../app/boot';
import { getCiabDashboardBasePath } from './section';
import './translations';
import type {
FetchSitesOptions,
Expand All @@ -16,7 +17,7 @@ import './style.scss';

boot( {
name: 'CIAB',
basePath: '/ciab',
basePath: getCiabDashboardBasePath( window.location.hostname ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just a temporary thing, having the ability to support both /ciab and my.woo.com? Seems like we should just remove the /ciab path, but this is perhaps to help with the transition so we don't immediately break the link between CIAB site dashboards and the MSD?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need this anyway for the Dashboard Live link. Since we only have one live environment, and the domain is random string, there's no way to distinguish it. So currently CIAB is accessible at <Dashboard Live link>/ciab/*, while dotcom's is at the root path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, live links!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use flags like app_variant to control which app entry to use for Dashboard Live link?

mainRoute: '/sites',
Logo: null,
supports: {
Expand Down
14 changes: 14 additions & 0 deletions client/dashboard/app-ciab/section.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const CIAB_DASHBOARD_SECTION_DEFINITION = {
name: 'dashboard-ciab',
module: 'dashboard/app-ciab',
};

const CIAB_DASHBOARD_ALLOWED_HOSTNAMES = [ 'my.woo.localhost', 'my.woo.com' ];

export function isAllowedCiabDashboardHost( host?: string ): boolean {
return CIAB_DASHBOARD_ALLOWED_HOSTNAMES.some( ( hostname ) => host?.startsWith( hostname ) );
}

export function getCiabDashboardBasePath( hostname: string ): string {
return CIAB_DASHBOARD_ALLOWED_HOSTNAMES.includes( hostname ) ? '/' : '/ciab';
}
10 changes: 10 additions & 0 deletions client/dashboard/app-dotcom/section.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { isAllowedCiabDashboardHost } from '../app-ciab/section';

export const DOTCOM_DASHBOARD_SECTION_DEFINITION = {
name: 'dashboard-dotcom',
module: 'dashboard/app-dotcom',
};

export function isAllowedDotcomDashboardHost( host?: string ): boolean {
return ! isAllowedCiabDashboardHost( host );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to list the allowed hostnames here instead of relying on CIAB?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot have a list because all Calypso live links are allowed but they are random. So we need to resort to regex to do that 🤔

Copy link
Contributor

@arthur791004 arthur791004 Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about host?.endsWith( '.calypso.live' )?

}
10 changes: 0 additions & 10 deletions client/dashboard/section.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
export const DASHBOARD_SECTION_PATHS = [ '/', '/sites', '/domains', '/emails', '/plugins', '/me' ];

export const DASHBOARD_SECTION_DEFINITION = {
name: 'dashboard-dotcom',
module: 'dashboard/app-dotcom',
};

export const DASHBOARD_CIAB_SECTION_DEFINITION = {
name: 'dashboard-ciab',
module: 'dashboard/app-ciab',
};
9 changes: 6 additions & 3 deletions client/dashboard/utils/is-dashboard-backport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ export function isDashboardBackport() {
return false;
}

// Calypso development environment can also load the dashboard via the following hostname,
// Calypso development environment can also load the dashboard via the following hostnames,
// in which case it's also not the backport.
if ( window?.location?.hostname?.startsWith( 'my.localhost' ) ) {
if (
window?.location?.hostname?.startsWith( 'my.localhost' ) ||
window?.location?.hostname?.startsWith( 'my.woo.localhost' )
) {
return false;
}

return ! [ '/v2', '/ciab' ].some( ( path ) => window?.location?.pathname?.startsWith( path ) );
return ! window?.location?.pathname?.startsWith( '/ciab' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this? If the pathname starts with /ciab, the hostname should be my.localhost:3000, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be a Dashboard Live link.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, I think you're right, that will be covered by if ( isDashboardEnv() ) 🤔

}
7 changes: 6 additions & 1 deletion client/dashboard/utils/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { isDashboardBackport } from './is-dashboard-backport';
* This function returns all the origins for the dashboard.
*/
export function dashboardOrigins(): string[] {
return [ 'http://my.localhost:3000', 'https://my.wordpress.com' ];
return [
'http://my.localhost:3000',
'https://my.wordpress.com',
'http://my.woo.localhost:3000',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw I kinda like my-woo.localhost:3000. Just to keep the number of sub-domain components consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I don't have strong opinion; I think I subconsciously followed the existing jetpack.cloud.localhost hostname. 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's fair. TIL about jetpack.cloud.localhost

'https://my.woo.com',
];
}

/**
Expand Down
2 changes: 2 additions & 0 deletions client/my-sites/checkout/get-thank-you-page-url/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ type ReceiptIdOrPlaceholder = ReceiptIdPlaceholder | PurchaseId | ReceiptId;
const allowedExternalSites = [
'my.wordpress.com',
'my.localhost',
'my.woo.com',
'my.woo.localhost',
'cloud.jetpack.com',
'jetpack.cloud.localhost',
'jetpack.com',
Expand Down
2 changes: 2 additions & 0 deletions client/my-sites/checkout/src/lib/pending-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,10 @@ function isRedirectAllowed( url: string, siteSlug: string | undefined ): boolean
'wpcalypso.wordpress.com',
'horizon.wordpress.com',
'my.wordpress.com',
'my.woo.com',
'calypso.localhost',
'my.localhost',
'my.woo.localhost',
'jetpack.cloud.localhost',
'cloud.jetpack.com',
'jetpack.com',
Expand Down
85 changes: 20 additions & 65 deletions client/server/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ import { stringify } from 'qs';
// eslint-disable-next-line no-restricted-imports
import superagent from 'superagent'; // Don't have Node.js fetch lib yet.
import {
DASHBOARD_SECTION_PATHS,
DASHBOARD_SECTION_DEFINITION,
DASHBOARD_CIAB_SECTION_DEFINITION,
} from 'calypso/dashboard/section';
isAllowedCiabDashboardHost,
CIAB_DASHBOARD_SECTION_DEFINITION,
} from 'calypso/dashboard/app-ciab/section';
import {
isAllowedDotcomDashboardHost,
DOTCOM_DASHBOARD_SECTION_DEFINITION,
} from 'calypso/dashboard/app-dotcom/section';
import { DASHBOARD_SECTION_PATHS } from 'calypso/dashboard/section';
import isDashboardEnv from 'calypso/dashboard/utils/is-dashboard-env';
import wooDnaConfig from 'calypso/jetpack-connect/woo-dna-config';
import { STEPPER_SECTION_DEFINITION } from 'calypso/landing/stepper/section';
Expand Down Expand Up @@ -1091,8 +1095,8 @@ export default function pages() {
);
}

// Multi-site Dashboard routing for development {calypso.localhost, wpcalypso.wordpress.com}.
if ( calypsoEnv !== 'production' && config.isEnabled( 'dashboard/v2' ) ) {
// Multi-site Dashboard routing.
if ( isDashboardEnv() || calypsoEnv === 'development' ) {
const handleRoute = ( section, sectionPath, entrypoint, reqFilter ) => {
app.get(
pathToRegExp( sectionPath ),
Expand All @@ -1103,62 +1107,18 @@ export default function pages() {
serverRender
);
};

DASHBOARD_SECTION_PATHS.forEach( ( route ) => {
handleRoute( DASHBOARD_SECTION_DEFINITION, route, 'entry-dashboard-dotcom', ( req ) => {
// Allow dashboard routes under my.localhost.
return req.get( 'host' ).startsWith( 'my.localhost' );
} );
} );

handleRoute( DASHBOARD_CIAB_SECTION_DEFINITION, '/ciab', 'entry-dashboard-ciab', ( req ) => {
// Allow CIAB routes under my.localhost.
return req.get( 'host' ).startsWith( 'my.localhost' );
handleRoute( DOTCOM_DASHBOARD_SECTION_DEFINITION, route, 'entry-dashboard-dotcom', ( req ) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a separate handleRoute call for each MSD-variant seems fine to me. Calypso v1 has that giant sections.ts file to do it all declaratively, and if we end up with enough MSD-variants maybe we want to do it declaratively too. But I'm not mad about having a copy-pasted line for each dashboard type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we want to do it declaratively too.

Hmm, I'm afraid if it's possible at all. We can only get the current request's host when we actually get the request, so that's why we need to "register" all the sections and then filter the correct one based on req.get('host') imperatively here 😬

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We have similar patterns for registering the dashboard section path. We could introduce a helper such as registerDashboardApp to simplify this, where each app only needs to provide data that conforms to a shared format. 🙂

isAllowedDotcomDashboardHost( req.get( 'host' ) )
);
} );

// Temporary support redirection for the /v2 route for backwards compatibility.
app.get( [ '/v2', '/v2/*' ], ( req, res, next ) => {
const host = req.get( 'host' );
const query = Object.keys( req.query ).length > 0 ? `?${ stringify( req.query ) }` : '';

if ( host.startsWith( 'calypso.localhost' ) ) {
const protocol = req.get( 'X-Forwarded-Proto' ) === 'https' ? 'https' : 'http';
const port = host.includes( ':' ) ? host.substring( host.indexOf( ':' ) ) : ':3000';

const redirectUrl = `${ protocol }://my.localhost${ port }${ req.path.slice(
'/v2'.length
) }${ query }`;
return res.redirect( 301, redirectUrl );
}

if ( host.startsWith( 'wpcalypso.wordpress.com' ) ) {
const redirectUrl = `https://my.wordpress.com${ req.path.slice( '/v2'.length ) }${ query }`;
return res.redirect( 301, redirectUrl );
}

next();
DASHBOARD_SECTION_PATHS.forEach( ( route ) => {
handleRoute( CIAB_DASHBOARD_SECTION_DEFINITION, route, 'entry-dashboard-ciab', ( req ) =>
isAllowedCiabDashboardHost( req.get( 'host' ) )
);
} );

// Temporary support redirection for the /ciab route for backwards compatibility.
// TODO: Remove /ciab once we no longer need to support the old testing link.
app.get( [ '/ciab', '/ciab/*' ], ( req, res, next ) => {
const host = req.get( 'host' );
const query = Object.keys( req.query ).length > 0 ? `?${ stringify( req.query ) }` : '';

if ( host.startsWith( 'calypso.localhost' ) ) {
const protocol = req.get( 'X-Forwarded-Proto' ) === 'https' ? 'https' : 'http';
const port = host.includes( ':' ) ? host.substring( host.indexOf( ':' ) ) : ':3000';

const redirectUrl = `${ protocol }://my.localhost${ port }${ req.path }${ query }`;
return res.redirect( 301, redirectUrl );
}

if ( host.startsWith( 'wpcalypso.wordpress.com' ) ) {
const redirectUrl = `https://my.wordpress.com${ req.path }${ query }`;
return res.redirect( 301, redirectUrl );
}

next();
handleRoute( CIAB_DASHBOARD_SECTION_DEFINITION, '/ciab', 'entry-dashboard-ciab', ( req ) => {
return isAllowedDotcomDashboardHost( req.get( 'host' ) );
} );
}

Expand All @@ -1185,14 +1145,9 @@ export default function pages() {
// Register CSP report route
registerCspReportRoute( app );

// Multi-site Dashboard routing for my.wordpress.com.
// Multi-site Dashboard routing.
// Return earlier since we don't need to set up any other routes.
if ( isDashboardEnv() ) {
DASHBOARD_SECTION_PATHS.forEach( ( route ) => {
handleSectionPath( DASHBOARD_SECTION_DEFINITION, route, 'entry-dashboard-dotcom' );
} );

handleSectionPath( DASHBOARD_CIAB_SECTION_DEFINITION, '/ciab', 'entry-dashboard-ciab' );
return app;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/wpcom-proxy-request/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,8 @@ const wpcomAllowedOrigins = [
'https://agencies.localhost:3000',
'http://my.localhost:3000',
'https://my.localhost:3000',
'http://my.woo.localhost:3000',
'https://my.woo.localhost:3000',
'http://calypso.localhost:3001',
'https://calypso.localhost:3001',
'https://calypso.live',
Expand Down