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 DEFAULT_ROLE = 'developer';
|
||||||
const FORGE_INTERNAL_URL = process.env.ACAI_FORGE_WEB_URL || "http://web:80";
|
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)
|
// Session-based credentials storage (ephemeral, per-session)
|
||||||
export const sessionCredentials = new Map();
|
export const sessionCredentials = new Map();
|
||||||
@@ -99,7 +106,7 @@ const readProjectAcaiFallback = () => {
|
|||||||
tokenHash: data.tokenHash || process.env.ACAI_TOKEN_HASH || null,
|
tokenHash: data.tokenHash || process.env.ACAI_TOKEN_HASH || null,
|
||||||
mode,
|
mode,
|
||||||
profileName: "acai-file",
|
profileName: "acai-file",
|
||||||
role: DEFAULT_ROLE,
|
role: resolveEffectiveRole(data.role),
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[Credentials] Failed to read .acai fallback: ${error.message}`);
|
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,
|
tokenHash: info.tokenHash || process.env.ACAI_TOKEN_HASH || null,
|
||||||
mode,
|
mode,
|
||||||
profileName: "project-info",
|
profileName: "project-info",
|
||||||
role: DEFAULT_ROLE,
|
role: resolveEffectiveRole(info.role),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -279,7 +286,7 @@ export const getSessionCredentials = async (sessionId, inlineCredentials = null)
|
|||||||
forge_host: process.env.ACAI_FORGE_HOST || null,
|
forge_host: process.env.ACAI_FORGE_HOST || null,
|
||||||
tokenHash: process.env.ACAI_TOKEN_HASH || null,
|
tokenHash: process.env.ACAI_TOKEN_HASH || null,
|
||||||
profileName: 'default',
|
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 { registerAcaiDeleteTool } from "./delete.js";
|
||||||
import { registerAcaiGlobTool } from "./glob.js";
|
import { registerAcaiGlobTool } from "./glob.js";
|
||||||
import { registerAcaiGrepTool } from "./grep.js";
|
import { registerAcaiGrepTool } from "./grep.js";
|
||||||
|
import { canEditCode } from "../helpers/roleCheck.js";
|
||||||
|
|
||||||
export function registerFileTools(server) {
|
export function registerFileTools(server) {
|
||||||
|
// Lectura: siempre disponible
|
||||||
registerAcaiViewTool(server);
|
registerAcaiViewTool(server);
|
||||||
registerAcaiGlobTool(server);
|
registerAcaiGlobTool(server);
|
||||||
registerAcaiGrepTool(server);
|
registerAcaiGrepTool(server);
|
||||||
|
// Escritura: solo si el rol puede editar codigo
|
||||||
|
if (canEditCode()) {
|
||||||
registerAcaiWriteTool(server);
|
registerAcaiWriteTool(server);
|
||||||
registerAcaiLineReplaceTool(server);
|
registerAcaiLineReplaceTool(server);
|
||||||
registerAcaiDeleteTool(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 { registerCheckModuleTool } from './check.js';
|
||||||
import { registerCheckModuleUsageTool } from './checkUsage.js';
|
import { registerCheckModuleUsageTool } from './checkUsage.js';
|
||||||
import { registerCompileModuleTool } from './compile.js';
|
import { registerCompileModuleTool } from './compile.js';
|
||||||
|
import { canEditCode } from '../helpers/roleCheck.js';
|
||||||
|
|
||||||
export function registerModuleTools(server) {
|
export function registerModuleTools(server) {
|
||||||
registerCheckModuleTool(server);
|
registerCheckModuleTool(server);
|
||||||
registerCheckModuleUsageTool(server);
|
registerCheckModuleUsageTool(server);
|
||||||
|
if (canEditCode()) {
|
||||||
registerCompileModuleTool(server);
|
registerCompileModuleTool(server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { registerSaveProjectStylesTool } from "./saveStyles.js";
|
import { registerSaveProjectStylesTool } from "./saveStyles.js";
|
||||||
import { registerGetWebUrlTool } from "./getWebUrl.js";
|
import { registerGetWebUrlTool } from "./getWebUrl.js";
|
||||||
|
import { canEditCode } from "../helpers/roleCheck.js";
|
||||||
|
|
||||||
export function registerProjectTools(server) {
|
export function registerProjectTools(server) {
|
||||||
|
registerGetWebUrlTool(server); // siempre
|
||||||
|
if (canEditCode()) {
|
||||||
registerSaveProjectStylesTool(server);
|
registerSaveProjectStylesTool(server);
|
||||||
registerGetWebUrlTool(server);
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { registerRecoverGitTools } from './rollback.js';
|
import { registerRecoverGitTools } from './rollback.js';
|
||||||
|
import { canEditCode } from '../helpers/roleCheck.js';
|
||||||
|
|
||||||
export function registerRemoteGitTools(server) {
|
export function registerRemoteGitTools(server) {
|
||||||
|
if (canEditCode()) {
|
||||||
registerRecoverGitTools(server);
|
registerRecoverGitTools(server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user