128 lines
5.5 KiB
TypeScript
128 lines
5.5 KiB
TypeScript
import { Routes, Route, Navigate } from 'react-router';
|
|
import { LoginPage } from './auth/LoginPage';
|
|
import { RegisterPage } from './auth/RegisterPage';
|
|
import { CallbackPage } from './auth/CallbackPage';
|
|
import { ProtectedRoute } from './auth/ProtectedRoute';
|
|
import { OrgResolver } from './auth/OrgResolver';
|
|
import { Layout } from './components/Layout';
|
|
import { RequireScope } from './components/RequireScope';
|
|
import { useScopes } from './auth/useScopes';
|
|
import { useOrgStore } from './auth/useOrganization';
|
|
|
|
import { VendorTenantsPage } from './pages/vendor/VendorTenantsPage';
|
|
import { CreateTenantPage } from './pages/vendor/CreateTenantPage';
|
|
import { TenantDetailPage } from './pages/vendor/TenantDetailPage';
|
|
import { VendorAuditPage } from './pages/vendor/VendorAuditPage';
|
|
import { CertificatesPage } from './pages/vendor/CertificatesPage';
|
|
import { InfrastructurePage } from './pages/vendor/InfrastructurePage';
|
|
import { VendorMetricsPage } from './pages/vendor/VendorMetricsPage';
|
|
import { EmailConfigPage } from './pages/vendor/EmailConfigPage';
|
|
import { TenantDashboardPage } from './pages/tenant/TenantDashboardPage';
|
|
import { TenantLicensePage } from './pages/tenant/TenantLicensePage';
|
|
import { SsoPage } from './pages/tenant/SsoPage';
|
|
import { TeamPage } from './pages/tenant/TeamPage';
|
|
import { SettingsPage } from './pages/tenant/SettingsPage';
|
|
import { TenantAuditPage } from './pages/tenant/TenantAuditPage';
|
|
import { OnboardingPage } from './pages/OnboardingPage';
|
|
|
|
function LandingRedirect() {
|
|
const scopes = useScopes();
|
|
const { organizations, currentOrgId, scopesReady } = useOrgStore();
|
|
const currentOrg = organizations.find((o) => o.id === currentOrgId);
|
|
|
|
// Wait for scopes to be fully resolved by OrgResolver before redirecting.
|
|
if (!scopesReady) {
|
|
return null;
|
|
}
|
|
|
|
// Vendor → vendor console
|
|
if (scopes.has('platform:admin')) {
|
|
return <Navigate to="/vendor/tenants" replace />;
|
|
}
|
|
// Tenant admin → tenant portal
|
|
if (scopes.has('tenant:manage')) {
|
|
return <Navigate to="/tenant" replace />;
|
|
}
|
|
// Regular user (operator/viewer) → server dashboard directly
|
|
if (currentOrg?.slug) {
|
|
window.location.href = `/t/${currentOrg.slug}/`;
|
|
return null;
|
|
}
|
|
// No org membership at all → onboarding (self-service tenant creation)
|
|
if (organizations.length === 0) {
|
|
return <Navigate to="/onboarding" replace />;
|
|
}
|
|
// Has org but no scopes resolved yet — stay on tenant portal
|
|
return <Navigate to="/tenant" replace />;
|
|
}
|
|
|
|
export function AppRouter() {
|
|
return (
|
|
<Routes>
|
|
<Route path="/login" element={<LoginPage />} />
|
|
<Route path="/register" element={<RegisterPage />} />
|
|
<Route path="/callback" element={<CallbackPage />} />
|
|
<Route element={<ProtectedRoute />}>
|
|
<Route element={<OrgResolver />}>
|
|
{/* Onboarding — outside Layout, shown to users with no tenants */}
|
|
<Route path="/onboarding" element={<OnboardingPage />} />
|
|
<Route element={<Layout />}>
|
|
{/* Vendor console */}
|
|
<Route path="/vendor/tenants" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<VendorTenantsPage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/tenants/new" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<CreateTenantPage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/tenants/:id" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<TenantDetailPage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/audit" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<VendorAuditPage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/certificates" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<CertificatesPage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/metrics" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<VendorMetricsPage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/infrastructure" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<InfrastructurePage />
|
|
</RequireScope>
|
|
} />
|
|
<Route path="/vendor/email" element={
|
|
<RequireScope scope="platform:admin" fallback={<Navigate to="/tenant" replace />}>
|
|
<EmailConfigPage />
|
|
</RequireScope>
|
|
} />
|
|
|
|
{/* Tenant portal */}
|
|
<Route path="/tenant" element={<TenantDashboardPage />} />
|
|
<Route path="/tenant/license" element={<TenantLicensePage />} />
|
|
<Route path="/tenant/sso" element={<SsoPage />} />
|
|
<Route path="/tenant/team" element={<TeamPage />} />
|
|
<Route path="/tenant/audit" element={<TenantAuditPage />} />
|
|
<Route path="/tenant/settings" element={<SettingsPage />} />
|
|
|
|
{/* Default redirect — vendor goes to /vendor/tenants, customer to /tenant */}
|
|
<Route index element={<LandingRedirect />} />
|
|
</Route>
|
|
</Route>
|
|
</Route>
|
|
</Routes>
|
|
);
|
|
}
|