Improve deployment process and add login redirect logic

Deployment improvements:
- Add template env files (.envs.example/) for documentation
- Create init-production.sh for one-time server setup
- Create build-activepieces.sh for building/deploying AP image
- Update deploy.sh with --deploy-ap flag
- Make custom-pieces-metadata.sql idempotent
- Update DEPLOYMENT.md with comprehensive instructions

Frontend:
- Redirect logged-in business owners from root domain to tenant dashboard
- Redirect logged-in users from /login to /dashboard on their tenant
- Log out customers on wrong subdomain instead of redirecting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-20 23:13:56 -05:00
parent 2a33e4cf57
commit f8d8419622
38 changed files with 2471 additions and 396 deletions

View File

@@ -321,9 +321,37 @@ const AppContent: React.FC = () => {
return hostname === 'localhost' || hostname === '127.0.0.1' || parts.length === 2;
};
// On root domain, ALWAYS show marketing site (even if logged in)
// Logged-in users will see a "Go to Dashboard" link in the navbar
// On root domain, handle logged-in users appropriately
if (isRootDomain()) {
// If user is logged in as a business user (owner, staff, resource), redirect to their tenant dashboard
if (user) {
const isBusinessUserOnRoot = ['owner', 'staff', 'resource'].includes(user.role);
const isCustomerOnRoot = user.role === 'customer';
const hostname = window.location.hostname;
const parts = hostname.split('.');
const baseDomain = parts.length >= 2 ? parts.slice(-2).join('.') : hostname;
const port = window.location.port ? `:${window.location.port}` : '';
const protocol = window.location.protocol;
// Business users on root domain: redirect to their tenant dashboard
if (isBusinessUserOnRoot && user.business_subdomain) {
window.location.href = `${protocol}//${user.business_subdomain}.${baseDomain}${port}/dashboard`;
return <LoadingScreen />;
}
// Customers on root domain: log them out and show the form
// Customers should only access their business subdomain
if (isCustomerOnRoot) {
deleteCookie('access_token');
deleteCookie('refresh_token');
localStorage.removeItem('masquerade_stack');
// Don't redirect, just let them see the page as unauthenticated
window.location.reload();
return <LoadingScreen />;
}
}
// Show marketing site for unauthenticated users and platform users (who should use platform subdomain)
return (
<Suspense fallback={<LoadingScreen />}>
<Routes>
@@ -480,16 +508,23 @@ const AppContent: React.FC = () => {
return <LoadingScreen />;
}
// RULE: Customers must be on their business subdomain
if (isCustomer && isPlatformDomain && user.business_subdomain) {
const port = window.location.port ? `:${window.location.port}` : '';
window.location.href = `${protocol}//${user.business_subdomain}.${baseDomain}${port}/`;
// RULE: Customers must only access their own business subdomain
// If on platform domain or wrong business subdomain, log them out and let them use the form
if (isCustomer && isPlatformDomain) {
deleteCookie('access_token');
deleteCookie('refresh_token');
localStorage.removeItem('masquerade_stack');
window.location.reload();
return <LoadingScreen />;
}
if (isCustomer && isBusinessSubdomain && user.business_subdomain && user.business_subdomain !== currentSubdomain) {
const port = window.location.port ? `:${window.location.port}` : '';
window.location.href = `${protocol}//${user.business_subdomain}.${baseDomain}${port}/`;
// Customer is on a different business's subdomain - log them out
// They might be trying to book with a different business
deleteCookie('access_token');
deleteCookie('refresh_token');
localStorage.removeItem('masquerade_stack');
window.location.reload();
return <LoadingScreen />;
}
@@ -723,7 +758,8 @@ const AppContent: React.FC = () => {
<Route path="/" element={<PublicPage />} />
<Route path="/book" element={<BookingFlow />} />
<Route path="/embed" element={<EmbedBooking />} />
<Route path="/login" element={<LoginPage />} />
{/* Logged-in business users on their own subdomain get redirected to dashboard */}
<Route path="/login" element={<Navigate to="/dashboard" replace />} />
<Route path="/sign/:token" element={<ContractSigning />} />
{/* Dashboard routes inside BusinessLayout */}