fix/instalacion-desatendida #23

Merged
acazares merged 11 commits from fix/instalacion-desatendida into development 2026-07-31 15:00:06 +00:00
2 changed files with 68 additions and 1 deletions
Showing only changes of commit 5b83a57d18 - Show all commits

View File

@@ -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);
});
});

View File

@@ -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}/`);
});
}