Control de modo editor/admin produccion/local
This commit is contained in:
@@ -18,6 +18,13 @@ import { fetchProjectInfo } from "./localClient.js";
|
||||
const DEFAULT_ROLE = 'developer';
|
||||
const FORGE_INTERNAL_URL = process.env.ACAI_FORGE_WEB_URL || "http://web:80";
|
||||
|
||||
const resolveEffectiveRole = (baseRole) => {
|
||||
if (process.env.ACAI_ROLE_OVERRIDE) return process.env.ACAI_ROLE_OVERRIDE;
|
||||
if (process.env.ACAI_MODE_OVERRIDE === "production") return "editor";
|
||||
if (process.env.ACAI_MODE === "production") return "editor";
|
||||
return baseRole || DEFAULT_ROLE;
|
||||
};
|
||||
|
||||
|
||||
// Session-based credentials storage (ephemeral, per-session)
|
||||
export const sessionCredentials = new Map();
|
||||
@@ -99,7 +106,7 @@ const readProjectAcaiFallback = () => {
|
||||
tokenHash: data.tokenHash || process.env.ACAI_TOKEN_HASH || null,
|
||||
mode,
|
||||
profileName: "acai-file",
|
||||
role: DEFAULT_ROLE,
|
||||
role: resolveEffectiveRole(data.role),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[Credentials] Failed to read .acai fallback: ${error.message}`);
|
||||
@@ -136,7 +143,7 @@ const resolveLocalProjectFallback = async () => {
|
||||
tokenHash: info.tokenHash || process.env.ACAI_TOKEN_HASH || null,
|
||||
mode,
|
||||
profileName: "project-info",
|
||||
role: DEFAULT_ROLE,
|
||||
role: resolveEffectiveRole(info.role),
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -279,7 +286,7 @@ export const getSessionCredentials = async (sessionId, inlineCredentials = null)
|
||||
forge_host: process.env.ACAI_FORGE_HOST || null,
|
||||
tokenHash: process.env.ACAI_TOKEN_HASH || null,
|
||||
profileName: 'default',
|
||||
role: 'developer', // Env fallback = local dev, full access
|
||||
role: resolveEffectiveRole('developer'), // Env fallback = local dev, full access
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -4,12 +4,17 @@ import { registerAcaiLineReplaceTool } from "./lineReplace.js";
|
||||
import { registerAcaiDeleteTool } from "./delete.js";
|
||||
import { registerAcaiGlobTool } from "./glob.js";
|
||||
import { registerAcaiGrepTool } from "./grep.js";
|
||||
import { canEditCode } from "../helpers/roleCheck.js";
|
||||
|
||||
export function registerFileTools(server) {
|
||||
// Lectura: siempre disponible
|
||||
registerAcaiViewTool(server);
|
||||
registerAcaiGlobTool(server);
|
||||
registerAcaiGrepTool(server);
|
||||
registerAcaiWriteTool(server);
|
||||
registerAcaiLineReplaceTool(server);
|
||||
registerAcaiDeleteTool(server);
|
||||
// Escritura: solo si el rol puede editar codigo
|
||||
if (canEditCode()) {
|
||||
registerAcaiWriteTool(server);
|
||||
registerAcaiLineReplaceTool(server);
|
||||
registerAcaiDeleteTool(server);
|
||||
}
|
||||
}
|
||||
|
||||
24
mcp-server/tools/helpers/roleCheck.js
Normal file
24
mcp-server/tools/helpers/roleCheck.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Helper central para determinar el rol efectivo del MCP y bloquear tools
|
||||
* peligrosas cuando el user es "editor".
|
||||
*
|
||||
* El rol se recibe principalmente via env var ACAI_ROLE_OVERRIDE inyectada
|
||||
* por el backend Python (agentic.py y cronjobs.py). Hay autoderivacion
|
||||
* defensiva en caso de que alguien lance el MCP sin el override:
|
||||
* - Si ACAI_MODE(_OVERRIDE) = "production" → rol editor por defecto.
|
||||
* - Si no → rol developer.
|
||||
*/
|
||||
export function getEffectiveRole() {
|
||||
if (process.env.ACAI_ROLE_OVERRIDE) return process.env.ACAI_ROLE_OVERRIDE;
|
||||
if (process.env.ACAI_MODE_OVERRIDE === "production") return "editor";
|
||||
if (process.env.ACAI_MODE === "production") return "editor";
|
||||
return "developer";
|
||||
}
|
||||
|
||||
/**
|
||||
* True si el rol efectivo puede editar archivos de codigo.
|
||||
* Los roles permitidos son todo lo que NO sea "editor".
|
||||
*/
|
||||
export function canEditCode() {
|
||||
return getEffectiveRole() !== "editor";
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
import { registerCheckModuleTool } from './check.js';
|
||||
import { registerCheckModuleUsageTool } from './checkUsage.js';
|
||||
import { registerCompileModuleTool } from './compile.js';
|
||||
import { canEditCode } from '../helpers/roleCheck.js';
|
||||
|
||||
export function registerModuleTools(server) {
|
||||
registerCheckModuleTool(server);
|
||||
registerCheckModuleUsageTool(server);
|
||||
registerCompileModuleTool(server);
|
||||
if (canEditCode()) {
|
||||
registerCompileModuleTool(server);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { registerSaveProjectStylesTool } from "./saveStyles.js";
|
||||
import { registerGetWebUrlTool } from "./getWebUrl.js";
|
||||
import { canEditCode } from "../helpers/roleCheck.js";
|
||||
|
||||
export function registerProjectTools(server) {
|
||||
registerSaveProjectStylesTool(server);
|
||||
registerGetWebUrlTool(server);
|
||||
registerGetWebUrlTool(server); // siempre
|
||||
if (canEditCode()) {
|
||||
registerSaveProjectStylesTool(server);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { registerRecoverGitTools } from './rollback.js';
|
||||
import { canEditCode } from '../helpers/roleCheck.js';
|
||||
|
||||
export function registerRemoteGitTools(server) {
|
||||
registerRecoverGitTools(server);
|
||||
if (canEditCode()) {
|
||||
registerRecoverGitTools(server);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user