fix(cras-install): dejar de rechazar el layout normal de carpetas de trabajo
isInsideWorkFolder miraba la relación en los dos sentidos, así que también rechazaba que las carpetas de trabajo colgaran de la de instalación. Ese es el layout NORMAL, no un error: constants.py del agente define DIR_ENTRADA = APP_DIR / "Entrada", así que una instalación correcta en /opt/cloudrestoreas reporta input_folder = /opt/cloudrestoreas/Entrada. Efecto: ninguna instalación ni actualización podía pasar, en Linux ni en Windows. Fallaba en resolveInstallPath —antes de abrir el run, así que no quedaba nada en la bitácora— con un mensaje que decía justo lo contrario de lo que ocurría: "la ruta está dentro de una carpeta de trabajo". Solo se libraban las instalaciones fuera de la ruta por omisión, por accidente del nombre. Se conserva el peligro que el guard existe para atajar: el binario dentro de Entrada/Procesados, donde el agente lo tomaría por un respaldo a procesar. La función no tenía ninguna prueba. Se agregan las dos direcciones, el caso exacto, la normalización de separador/caja/barra final y el prefijo que no es de carpeta (/srv/entradas vs /srv/entrada). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
effectivePlatform,
|
||||
installPlatformVerdict,
|
||||
isCrasPlatform,
|
||||
isInsideWorkFolder,
|
||||
isNewer,
|
||||
isValidVersion,
|
||||
osToPlatform,
|
||||
@@ -201,3 +202,61 @@ describe('installPlatformVerdict', () => {
|
||||
expect(installPlatformVerdict(null, 'windows', ' WINDOWS ')).toBe('ok');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Guard de la ruta de instalación contra las carpetas de trabajo del agente.
|
||||
*
|
||||
* No tenía ni una prueba, y con la relación mirada en los dos sentidos rechazaba el layout
|
||||
* NORMAL —`DIR_ENTRADA = APP_DIR / "Entrada"` en constants.py del agente— así que ninguna
|
||||
* instalación ni actualización podía pasar. Se salvaban solo las instalaciones fuera de la ruta
|
||||
* por omisión, por accidente del nombre.
|
||||
*/
|
||||
describe('isInsideWorkFolder', () => {
|
||||
it('acepta el layout normal: las carpetas de trabajo cuelgan de la de instalación', () => {
|
||||
expect(
|
||||
isInsideWorkFolder('/opt/cloudrestoreas', [
|
||||
'/opt/cloudrestoreas/Entrada',
|
||||
'/opt/cloudrestoreas/Procesados'
|
||||
])
|
||||
).toBe(false);
|
||||
expect(
|
||||
isInsideWorkFolder('C:\\Aduanasoft\\CloudRestoreAS', [
|
||||
'C:\\Aduanasoft\\CloudRestoreAS\\Entrada'
|
||||
])
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('rechaza el binario DENTRO de una carpeta de trabajo, que es el peligro real', () => {
|
||||
// Ahí el agente tomaría su propio ejecutable por un respaldo a procesar.
|
||||
expect(isInsideWorkFolder('/srv/entrada/cras', ['/srv/entrada'])).toBe(true);
|
||||
expect(
|
||||
isInsideWorkFolder('D:\\Respaldos\\Entrada\\app', ['D:\\Respaldos\\Entrada'])
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('rechaza instalar exactamente EN la carpeta de trabajo', () => {
|
||||
expect(isInsideWorkFolder('/srv/entrada', ['/srv/entrada'])).toBe(true);
|
||||
expect(isInsideWorkFolder('/srv/entrada/', ['/srv/entrada'])).toBe(true);
|
||||
});
|
||||
|
||||
it('normaliza separadores, barra final y caja antes de comparar', () => {
|
||||
expect(isInsideWorkFolder('C:/Respaldos/Entrada/app', ['c:\\respaldos\\entrada\\'])).toBe(
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('un prefijo que no es de carpeta no cuenta como estar dentro', () => {
|
||||
// Es el caso que dejaba pasar a Principal: -win rompe el prefijo de carpeta.
|
||||
expect(
|
||||
isInsideWorkFolder('C:\\Aduanasoft\\CloudRestoreAS', [
|
||||
'C:\\Aduanasoft\\CloudRestoreAS-win\\Entrada'
|
||||
])
|
||||
).toBe(false);
|
||||
expect(isInsideWorkFolder('/srv/entradas', ['/srv/entrada'])).toBe(false);
|
||||
});
|
||||
|
||||
it('ignora carpetas vacías o sin reportar en lugar de bloquear', () => {
|
||||
expect(isInsideWorkFolder('/opt/cloudrestoreas', [null, undefined, '', ' '])).toBe(false);
|
||||
expect(isInsideWorkFolder('', ['/srv/entrada'])).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -189,6 +189,14 @@ export function isDefaultInstallPath(
|
||||
*
|
||||
* Instalar el binario dentro de `Entrada`/`Procesados` sería grave: el agente vigila esa
|
||||
* carpeta y trataría de procesar sus propios archivos como si fueran respaldos.
|
||||
*
|
||||
* La relación se mira en UN solo sentido, y eso es deliberado. La carpeta de trabajo **debajo**
|
||||
* de la de instalación es el layout normal, no un error: `constants.py` del agente define
|
||||
* `DIR_ENTRADA = APP_DIR / "Entrada"`, así que una instalación correcta en
|
||||
* `/opt/cloudrestoreas` reporta `input_folder = /opt/cloudrestoreas/Entrada`. Cuando esto también
|
||||
* rechazaba ese caso, ninguna instalación ni actualización podía pasar: fallaba en
|
||||
* resolveInstallPath, antes de abrir el run, con un mensaje que decía justo lo contrario de lo
|
||||
* que ocurría. Solo se salvaban las instalaciones fuera de la ruta por omisión, por accidente.
|
||||
*/
|
||||
export function isInsideWorkFolder(
|
||||
installPath: string | null | undefined,
|
||||
@@ -206,7 +214,7 @@ export function isInsideWorkFolder(
|
||||
return workFolders.some((folder) => {
|
||||
const base = norm(folder);
|
||||
if (!base) return false;
|
||||
return target === base || target.startsWith(`${base}/`) || base.startsWith(`${target}/`);
|
||||
return target === base || target.startsWith(`${base}/`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user