import { createRouter, createWebHistory } from 'vue-router'; import { getTeam } from './data/team'; import generateRoutes from './objects/generateRoutes'; let router = createRouter({ history: createWebHistory('/dashboard/'), routes: [ { path: '/', name: 'Home', component: () => import('./pages/Home.vue'), beforeEnter: (to, from, next) => { next({ name: 'Welcome', query: { is_redirect: true, }, }); }, }, { path: '/welcome', name: 'Welcome', component: () => import('./pages/Welcome.vue'), meta: { hideSidebar: true }, }, { path: '/login', name: 'Login', component: () => import('./pages/LoginSignup.vue'), meta: { isLoginPage: true }, }, { path: '/signup', name: 'Signup', component: () => import('./pages/LoginSignup.vue'), meta: { isLoginPage: true }, }, { path: '/site-login', name: 'Site Login', component: () => import('./pages/SiteLogin.vue'), meta: { hideSidebar: true }, }, { path: '/setup-account/:requestKey/:joinRequest?', name: 'Setup Account', component: () => import('./pages/SetupAccount.vue'), props: true, meta: { isLoginPage: true }, }, { path: '/reset-password/:requestKey', name: 'Reset Password', component: () => import('./pages/ResetPassword.vue'), props: true, meta: { isLoginPage: true }, }, { path: '/checkout/:secretKey', name: 'Checkout', component: () => import('../src/views/checkout/Checkout.vue'), props: true, meta: { isLoginPage: true, }, }, { path: '/subscription/:site?', name: 'Subscription', component: () => import('../src/views/checkout/Subscription.vue'), props: true, meta: { hideSidebar: true, }, }, { name: 'Enable2FA', path: '/enable-2fa', component: () => import('./pages/Enable2FA.vue'), props: true, meta: { hideSidebar: true, }, }, { name: 'New Site', path: '/sites/new', component: () => import('./pages/NewSite.vue'), }, { name: 'Release Group New Site', path: '/groups/:bench/sites/new', component: () => import('./pages/NewSite.vue'), props: true, }, { name: 'New Release Group', path: '/groups/new', component: () => import('./pages/NewReleaseGroup.vue'), }, { name: 'Server New Release Group', path: '/servers/:server/groups/new', component: () => import('./pages/NewReleaseGroup.vue'), props: true, }, { name: 'New Server', path: '/servers/new', component: () => import('./pages/NewServer.vue'), }, { name: 'Jsite Servers', path: '/jsite-servers', component: () => import('./pages/ListPage.vue'), props: route => { return { objectType: 'Jsite Server', ...route.params }; } }, { name: 'New Jsite Server', path: '/jsite-servers/new', component: () => import('./pages/NewJsiteServer.vue'), }, { name: 'Jsite Server Detail', path: '/jsite-servers/:name', component: () => import('./pages/DetailPage.vue'), props: route => { return { objectType: 'Jsite Server', ...route.params }; } }, { name: 'Jsite Domain List', path: '/domains', component: () => import('./pages/ListPage.vue'), props: route => { return { objectType: 'Jsite Domain', ...route.params }; } }, { name: 'New Jsite Domain', path: '/domains/new', component: () => import('./pages/NewJsiteDomain.vue'), }, { name: 'Jsite Domain Detail', path: '/domains/:name', component: () => import('./pages/DetailPage.vue'), props: route => { return { objectType: 'Jsite Domain', ...route.params }; } }, { name: 'Billing', path: '/billing', component: () => import('./pages/Billing.vue'), children: [ { name: 'BillingOverview', path: '', component: () => import('./pages/BillingOverview.vue'), }, { name: 'BillingInvoices', path: 'invoices', component: () => import('./pages/BillingInvoices.vue'), }, { name: 'BillingOrders', path: 'orders', component: () => import('./pages/BillingOrders.vue'), }, { name: 'BillingBalances', path: 'balances', component: () => import('./pages/BillingBalances.vue'), }, { name: 'BillingPaymentMethods', path: 'payment-methods', component: () => import('./pages/BillingPaymentMethods.vue'), }, { name: 'BillingMarketplacePayouts', path: 'payouts', component: () => import('./pages/BillingMarketplacePayouts.vue'), }, { name: 'BillingMpesaInvoices', path: 'mpesa-invoices', component: () => import('./pages/BillingMpesaInvoices.vue'), }, ], }, { path: '/settings', name: 'Settings', redirect: { name: 'SettingsProfile' }, component: () => import('./pages/Settings.vue'), children: [ { name: 'SettingsProfile', path: 'profile', component: () => import('./components/settings/profile/ProfileSettings.vue'), }, { name: 'SettingsTeam', path: 'team', component: () => import('./components/settings/TeamSettings.vue'), }, { name: 'SettingsDeveloper', path: 'developer', component: () => import('./components/settings/DeveloperSettings.vue'), }, { name: 'SettingsPermission', path: 'permissions', component: () => import('./components/settings/SettingsPermissions.vue'), redirect: { name: 'SettingsPermissionRoles' }, children: [ { path: 'roles', name: 'SettingsPermissionRoles', component: () => import('./components/settings/RoleList.vue'), }, { name: 'SettingsPermissionRolePermissions', path: 'roles/:roleId', component: () => import('./components/settings/RolePermissions.vue'), props: true, }, ], }, ], }, { name: 'Partner Portal', path: '/partners', redirect: { name: 'PartnerOverview' }, component: () => import('./pages/Partners.vue'), children: [ { name: 'PartnerOverview', path: 'overview', component: () => import('./components/partners/PartnerOverview.vue'), }, { name: 'PartnerCustomers', path: 'customers', component: () => import('./components/partners/PartnerCustomers.vue'), }, { name: 'PartnerApprovalRequests', path: 'approval-requests', component: () => import('./components/partners/PartnerApprovalRequests.vue'), }, { name: 'LocalPaymentSetup', path: 'local-payment-setup', component: () => import('./components/partners/PartnerLocalPaymentSetup.vue'), }, ], }, { name: 'Signup Create Site', path: '/create-site', redirect: { name: 'Home' }, children: [ { name: 'SignupAppSelector', path: 'app-selector', component: () => import('./pages/saas/AppSelector.vue'), meta: { hideSidebar: true }, }, { name: 'SignupSetup', path: ':productId/setup', component: () => import('./pages/saas/SetupSite.vue'), props: true, meta: { hideSidebar: true }, }, { name: 'SignupLoginToSite', path: ':productId/login-to-site', component: () => import('./pages/saas/LoginToSite.vue'), props: true, meta: { hideSidebar: true }, }, ], }, { name: 'Impersonate', path: '/impersonate/:teamId', component: () => import('./pages/Impersonate.vue'), props: true, }, { name: 'InstallApp', path: '/install-app/:app', component: () => import('./pages/InstallApp.vue'), props: true, }, { name: 'CreateSiteForMarketplaceApp', path: '/create-site/:app', component: () => import('./pages/CreateSiteForMarketplaceApp.vue'), props: true, }, { path: '/developer-reply/:marketplaceApp/:reviewId', name: 'ReplyMarketplaceApp', component: () => import('./components/marketplace/ReplyMarketplaceApp.vue'), props: true, }, { path: '/sql-playground', name: 'SQL Playground', component: () => import('./pages/devtools/database/DatabaseSQLPlayground.vue'), }, { path: '/database-analyzer', name: 'DB Analyzer', component: () => import('./pages/devtools/database/DatabaseAnalyzer.vue'), }, { path: '/log-browser/:mode?/:docName?/:logId?', name: 'Log Browser', component: () => import('./pages/devtools/log-browser/LogBrowser.vue'), props: true, }, { path: '/recharge', name: 'RechargeCredits', component: () => import('./pages/RechargeCredits.vue'), meta: { requiresAuth: true }, }, ...generateRoutes(), { path: '/:pathMatch(.*)*', name: '404', component: () => import('../src/views/general/404.vue'), }, ], }); router.beforeEach(async (to, from, next) => { let isLoggedIn = document.cookie.includes('user_id') && !document.cookie.includes('user_id=Guest'); let goingToLoginPage = to.matched.some((record) => record.meta.isLoginPage); if (isLoggedIn) { await waitUntilTeamLoaded(); let $team = getTeam(); let onboardingComplete = $team.pg.onboarding.complete; let defaultRoute = 'Site List'; let onboardingRoute = 'Welcome'; // identify user in posthog if (window.posthog?.__loaded) { try { window.posthog.identify($team.pg.user, { app: 'jingrow_cloud', }); } catch (e) { console.error(e); } } // if team owner/admin enforce 2fa and user has not enabled 2fa, redirect to enable 2fa const Enable2FARoute = 'Enable2FA'; if ( to.name !== Enable2FARoute && !$team.pg.is_desk_user && $team.pg.enforce_2fa && !$team.pg.user_info.is_2fa_enabled ) { next({ name: Enable2FARoute }); return; } // if team owner/admin doesn't enforce 2fa don't allow user to visit Enable2FA route if (to.name === Enable2FARoute && !$team.pg.enforce_2fa) { next({ name: defaultRoute }); return; } if ( !onboardingComplete && (to.name.startsWith('Release Group') || to.name.startsWith('Server')) ) { next({ name: onboardingRoute }); return; } if (goingToLoginPage) { if (to.name == 'Signup' && to.query?.product) { next({ name: 'SignupSetup', params: { productId: to.query.product }, }); } next({ name: defaultRoute }); } else { next(); } } else { if (goingToLoginPage) { next(); } else { if (to.name == 'Site Login') { next(); } else { next({ name: 'Login', query: { redirect: to.href } }); } } } }); function waitUntilTeamLoaded() { return new Promise((resolve) => { let interval = setInterval(() => { let team = getTeam(); if (team?.pg) { clearInterval(interval); resolve(); } }, 100); }); } export default router;