mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
feat(server): Implement Cursor CLI permissions management
Added new routes and handlers for managing Cursor CLI permissions, including: - GET /api/setup/cursor-permissions: Retrieve current permissions configuration and available profiles. - POST /api/setup/cursor-permissions/profile: Apply a predefined permission profile (global or project). - POST /api/setup/cursor-permissions/custom: Set custom permissions for a project. - DELETE /api/setup/cursor-permissions: Delete project-level permissions, reverting to global settings. - GET /api/setup/cursor-permissions/example: Provide an example config file for a specified profile. Also introduced a new service for handling Cursor CLI configuration files and updated the UI to support permissions management. Affected files: - Added new routes in index.ts and cursor-config.ts - Created cursor-config-service.ts for permissions management logic - Updated UI components to display and manage permissions 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -17,6 +17,11 @@ import {
|
||||
createGetCursorConfigHandler,
|
||||
createSetCursorDefaultModelHandler,
|
||||
createSetCursorModelsHandler,
|
||||
createGetCursorPermissionsHandler,
|
||||
createApplyPermissionProfileHandler,
|
||||
createSetCustomPermissionsHandler,
|
||||
createDeleteProjectPermissionsHandler,
|
||||
createGetExampleConfigHandler,
|
||||
} from './routes/cursor-config.js';
|
||||
|
||||
export function createSetupRoutes(): Router {
|
||||
@@ -38,5 +43,12 @@ export function createSetupRoutes(): Router {
|
||||
router.post('/cursor-config/default-model', createSetCursorDefaultModelHandler());
|
||||
router.post('/cursor-config/models', createSetCursorModelsHandler());
|
||||
|
||||
// Cursor CLI Permissions routes
|
||||
router.get('/cursor-permissions', createGetCursorPermissionsHandler());
|
||||
router.post('/cursor-permissions/profile', createApplyPermissionProfileHandler());
|
||||
router.post('/cursor-permissions/custom', createSetCustomPermissionsHandler());
|
||||
router.delete('/cursor-permissions', createDeleteProjectPermissionsHandler());
|
||||
router.get('/cursor-permissions/example', createGetExampleConfigHandler());
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,36 @@
|
||||
* - GET /api/setup/cursor-config - Get current configuration
|
||||
* - POST /api/setup/cursor-config/default-model - Set default model
|
||||
* - POST /api/setup/cursor-config/models - Set enabled models
|
||||
*
|
||||
* Cursor CLI Permissions endpoints:
|
||||
* - GET /api/setup/cursor-permissions - Get permissions config
|
||||
* - POST /api/setup/cursor-permissions/profile - Apply a permission profile
|
||||
* - POST /api/setup/cursor-permissions/custom - Set custom permissions
|
||||
* - DELETE /api/setup/cursor-permissions - Delete project permissions (use global)
|
||||
*/
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
import { CursorConfigManager } from '../../../providers/cursor-config-manager.js';
|
||||
import { CURSOR_MODEL_MAP, type CursorModelId } from '@automaker/types';
|
||||
import {
|
||||
CURSOR_MODEL_MAP,
|
||||
CURSOR_PERMISSION_PROFILES,
|
||||
type CursorModelId,
|
||||
type CursorPermissionProfile,
|
||||
type CursorCliPermissions,
|
||||
} from '@automaker/types';
|
||||
import {
|
||||
readGlobalConfig,
|
||||
readProjectConfig,
|
||||
getEffectivePermissions,
|
||||
applyProfileToProject,
|
||||
applyProfileGlobally,
|
||||
writeProjectConfig,
|
||||
deleteProjectConfig,
|
||||
detectProfile,
|
||||
hasProjectConfig,
|
||||
getAvailableProfiles,
|
||||
generateExampleConfig,
|
||||
} from '../../../services/cursor-config-service.js';
|
||||
import { getErrorMessage, logError } from '../common.js';
|
||||
|
||||
/**
|
||||
@@ -134,3 +159,209 @@ export function createSetCursorModelsHandler() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Cursor CLI Permissions Handlers
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Creates handler for GET /api/setup/cursor-permissions
|
||||
* Returns current permissions configuration and available profiles
|
||||
*/
|
||||
export function createGetCursorPermissionsHandler() {
|
||||
return async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const projectPath = req.query.projectPath as string | undefined;
|
||||
|
||||
// Get global config
|
||||
const globalConfig = await readGlobalConfig();
|
||||
|
||||
// Get project config if path provided
|
||||
const projectConfig = projectPath ? await readProjectConfig(projectPath) : null;
|
||||
|
||||
// Get effective permissions
|
||||
const effectivePermissions = await getEffectivePermissions(projectPath);
|
||||
|
||||
// Detect which profile is active
|
||||
const activeProfile = detectProfile(effectivePermissions);
|
||||
|
||||
// Check if project has its own config
|
||||
const hasProject = projectPath ? await hasProjectConfig(projectPath) : false;
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
globalPermissions: globalConfig?.permissions || null,
|
||||
projectPermissions: projectConfig?.permissions || null,
|
||||
effectivePermissions,
|
||||
activeProfile,
|
||||
hasProjectConfig: hasProject,
|
||||
availableProfiles: getAvailableProfiles(),
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error, 'Get Cursor permissions failed');
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: getErrorMessage(error),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates handler for POST /api/setup/cursor-permissions/profile
|
||||
* Applies a predefined permission profile
|
||||
*/
|
||||
export function createApplyPermissionProfileHandler() {
|
||||
return async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const { profileId, projectPath, scope } = req.body as {
|
||||
profileId: CursorPermissionProfile;
|
||||
projectPath?: string;
|
||||
scope: 'global' | 'project';
|
||||
};
|
||||
|
||||
// Validate profile
|
||||
const validProfiles = CURSOR_PERMISSION_PROFILES.map((p) => p.id);
|
||||
if (!validProfiles.includes(profileId)) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: `Invalid profile. Valid profiles: ${validProfiles.join(', ')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (scope === 'project') {
|
||||
if (!projectPath) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'projectPath is required for project scope',
|
||||
});
|
||||
return;
|
||||
}
|
||||
await applyProfileToProject(projectPath, profileId);
|
||||
} else {
|
||||
await applyProfileGlobally(profileId);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `Applied "${profileId}" profile to ${scope}`,
|
||||
scope,
|
||||
profileId,
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error, 'Apply Cursor permission profile failed');
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: getErrorMessage(error),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates handler for POST /api/setup/cursor-permissions/custom
|
||||
* Sets custom permissions for a project
|
||||
*/
|
||||
export function createSetCustomPermissionsHandler() {
|
||||
return async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const { projectPath, permissions } = req.body as {
|
||||
projectPath: string;
|
||||
permissions: CursorCliPermissions;
|
||||
};
|
||||
|
||||
if (!projectPath) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'projectPath is required',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!permissions || !Array.isArray(permissions.allow) || !Array.isArray(permissions.deny)) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'permissions must have allow and deny arrays',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await writeProjectConfig(projectPath, {
|
||||
version: 1,
|
||||
permissions,
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Custom permissions saved',
|
||||
permissions,
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error, 'Set custom Cursor permissions failed');
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: getErrorMessage(error),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates handler for DELETE /api/setup/cursor-permissions
|
||||
* Deletes project-level permissions (falls back to global)
|
||||
*/
|
||||
export function createDeleteProjectPermissionsHandler() {
|
||||
return async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const projectPath = req.query.projectPath as string;
|
||||
|
||||
if (!projectPath) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'projectPath query parameter is required',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await deleteProjectConfig(projectPath);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Project permissions deleted, using global config',
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error, 'Delete Cursor project permissions failed');
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: getErrorMessage(error),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates handler for GET /api/setup/cursor-permissions/example
|
||||
* Returns an example config file for a profile
|
||||
*/
|
||||
export function createGetExampleConfigHandler() {
|
||||
return async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const profileId = (req.query.profileId as CursorPermissionProfile) || 'development';
|
||||
|
||||
const exampleConfig = generateExampleConfig(profileId);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
profileId,
|
||||
config: exampleConfig,
|
||||
});
|
||||
} catch (error) {
|
||||
logError(error, 'Get example Cursor config failed');
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: getErrorMessage(error),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user