feat: enforce per-user module access in Makelore
This commit is contained in:
37
src/App.tsx
37
src/App.tsx
@@ -31,7 +31,11 @@ import { useProviderStore } from './stores/providers';
|
||||
import { useAuthStore } from './stores/auth';
|
||||
import { useOpencodeStore } from './stores/opencode';
|
||||
import { useProjectConfigStore } from './stores/project-config';
|
||||
import { AI_MODULE_SELECTION_PATH } from './lib/ai-modules';
|
||||
import {
|
||||
AI_MODULE_SELECTION_PATH,
|
||||
getGuardedAiModuleForPath,
|
||||
isAiModuleAllowed,
|
||||
} from './lib/ai-modules';
|
||||
import { useUserSyncStore } from './stores/user-sync';
|
||||
import { flushPendingAgentSessionSync } from '@/lib/agent-session-sync';
|
||||
import { subscribeHostEvent } from '@/lib/host-events';
|
||||
@@ -118,25 +122,8 @@ function getReturnPath(location: ReturnType<typeof useLocation>): string {
|
||||
return `${location.pathname}${location.search}`;
|
||||
}
|
||||
|
||||
const PROGRAMMING_ROUTE_PREFIXES = [
|
||||
'/project-config',
|
||||
'/makelore-home',
|
||||
'/kangaroo',
|
||||
'/subagents',
|
||||
'/chat',
|
||||
'/deliverables',
|
||||
'/workbench',
|
||||
'/opencode-chat',
|
||||
'/projects',
|
||||
'/sessions',
|
||||
'/models',
|
||||
'/settings',
|
||||
] as const;
|
||||
|
||||
function isProgrammingRoute(pathname: string): boolean {
|
||||
return PROGRAMMING_ROUTE_PREFIXES.some(
|
||||
(route) => pathname === route || pathname.startsWith(`${route}/`),
|
||||
);
|
||||
return getGuardedAiModuleForPath(pathname) === 'programming';
|
||||
}
|
||||
|
||||
function ProtectedLayout({
|
||||
@@ -152,6 +139,8 @@ function ProtectedLayout({
|
||||
}) {
|
||||
const location = useLocation();
|
||||
const authenticated = useAuthStore((state) => state.isAuthenticated());
|
||||
const moduleAccess = useAuthStore((state) => state.moduleAccess);
|
||||
const requestedModule = getGuardedAiModuleForPath(location.pathname);
|
||||
const allowsAnonymousImageWorkspace = imageWorkspaceLocalDevelopment
|
||||
&& (location.pathname === '/image-canvas'
|
||||
|| location.pathname.startsWith('/image-canvas/')
|
||||
@@ -176,6 +165,10 @@ function ProtectedLayout({
|
||||
);
|
||||
}
|
||||
|
||||
if (authenticated && requestedModule && !isAiModuleAllowed(requestedModule, moduleAccess)) {
|
||||
return <Navigate to={AI_MODULE_SELECTION_PATH} replace />;
|
||||
}
|
||||
|
||||
return <MainLayout />;
|
||||
}
|
||||
|
||||
@@ -264,6 +257,9 @@ function App() {
|
||||
const authInitialized = useAuthStore((state) => state.initialized);
|
||||
const authenticated = useAuthStore((state) => state.isAuthenticated());
|
||||
const authAccessToken = useAuthStore((state) => state.accessToken);
|
||||
const programmingModuleAllowed = useAuthStore(
|
||||
(state) => state.moduleAccess.programming,
|
||||
);
|
||||
const bootstrapUserSync = useUserSyncStore((state) => state.bootstrap);
|
||||
const setupReady = setupComplete || skipSetupForE2E || rendererOnlyPreview;
|
||||
const authRequired = !skipSetupForE2E && !rendererOnlyPreview;
|
||||
@@ -325,9 +321,10 @@ function App() {
|
||||
useEffect(() => {
|
||||
if (rendererOnlyPreview) return;
|
||||
if (!setupReady) return;
|
||||
if (!programmingModuleAllowed) return;
|
||||
if (!isProgrammingRoute(location.pathname)) return;
|
||||
initProviders();
|
||||
}, [initProviders, location.pathname, rendererOnlyPreview, setupReady]);
|
||||
}, [initProviders, location.pathname, programmingModuleAllowed, rendererOnlyPreview, setupReady]);
|
||||
|
||||
useEffect(() => {
|
||||
if (rendererOnlyPreview) return;
|
||||
|
||||
Reference in New Issue
Block a user